Florian Reichle
Angaben zu den Daten
Das verwendete Dataset des Projekts: https://www.kaggle.com/datasets/gregorut/videogamesales
Dies besteht aus den Daten von https://www.vgchartz.com/ für die Jahre 1980 bis 2016
und umfasst die Folgenden Spalten bzw.Daten.
- Rank - Die Platzierung des Spiels nach Anzahl der Verkäufen
- Name - Der Name des Spiels
- Platform - Die Platform auf der das Spiel veröffentlicht wurde (z.B.
PC,PS4, etc.)
- Year - Das Jahr der Veröffentlichung des Spiels
- Genre - Das Genre des Spiels (z.B. Sport,Action, Puzzle)
- Publisher - Der Publisher des Spiels
- NA_Sales - Die Anzahl der Verkäufe in Nord-Amerika (in
millionen)
- EU_Sales - Die Anzahl der Verkäufe in Europa (in millionen)
- JP_Sales - Die Anzahl der Verkäufe in Japan (in millionen)
- Other_Sales - Die Anzahl der Verkäufe im Rest der Welt (in
millionen)
- Global_Sales - Die Anzahl der Verkäufe Weltweit (in millionen)
Inhaltsverzeichnis
- Releaseanalyse
- Platformanalyse
- Publisheranalyse
- Genreanalyse
- Genreverteilung pro Jahr
- Publisher Genres
- Kritischer Rückblick
Thesen
Bevor wir mit der Analyse der Daten beginnen können Stellen wir
erstmal ein paar Thesen bzw. Fragestellungen auf die wir im laufe des
Projekts hinterfragen bzw beantworten wollen.
Welche Jahre sind die besten in der Anzahl der releasten Games
und Sales? Antwort
Werden heutzutage mehr Spiele Releast und Verkauft als noch 1980?
Antwort
Welche Jahre sind die besten in Anzahl Sales pro Game? Werden
neuere Spiele automatisch mehr Gekauft? Antwort
Welche Plattform ist die beste in Anzahl verkäufen? Welche in
Anzahl der Game Releases? Antwort
Haben Ältere Platformen Automatisch mehr Spiele und Verkäufe? Antwort
Favorisieren verschiedene Regionen verschiedene Platformen?
Verkaufen die Regionenheimischen Platformen automatisch auch die meisten
Spiele? Antwort
Wie Entwickeln sich die Verkäufe pro Platform im laufe der Jahre?
Haben Platformen kurz nach Release den größten “Hype”? Antwort
Bestimmte Publisher häufen sich in Anzahl der Spiele und der
Verkäufen (z.B. Nintendo, EA, Activision Blizzard) Antwort
Gibt es regionale Unterschiede in den Publishern? Werden
Regioneninterne Publisher Favoritisiert? Antwort
Wie sind die Genres der Spiele verteilt? Häufen sich bestimmte
Genres bei Anzahl und Verkaufszahlen? Gibt es Genres die
besser/schlechter Performen als sie sollten? Antwort
Gibt es regionale Unterschiede in den Genres? (Gibt es Regionen
die Spezifische Genres Favorisieren welche in anderen Regionen nur eine
geringe Rolle spielt?) Antwort
Wie haben sich die Genres über die Jahre entwickelt? Antwort
Gibt es Genres die mal großen Einfluss hatten und nun
Bedeutungslos sind? Antwort
Gibt es Publisher die bestimmte Genres bevorzugen bzw. Publisher
deren Games eines bestimmten Genres sich besonders gut Verkaufen? Antwort
Daten und Librarys
Nach dem Vorstellen der Daten und dem aufstellen der initialen Thesen
können wir nun mit dem einlesen der Daten beginnen.
Zusätzlich erstellen wir noch eine Farbpalette und importieren die
Librarys
library(readr)
library(tidyverse)
library(forcats)
library(plotly)
library(knitr, warn.conflicts = FALSE, quietly=TRUE)
library(RColorBrewer)
library(stringr)
library(dygraphs)
library(xts)
suppressPackageStartupMessages(library(dplyr))
myPalette <- brewer.pal(10, "Paired")
vgsales <- read_csv("vgsales.csv")
Rows: 16598 Columns: 11
-- Column specification ------------------------------------------------------------------------------------------------------------------------------------------------------
Delimiter: ","
chr (5): Name, Platform, Year, Genre, Publisher
dbl (6): Rank, NA_Sales, EU_Sales, JP_Sales, Other_Sales, Global_Sales
i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Video Game Releases
Game Releases over the Years
Game Amount
Unsere erste These war “Welche Jahre sind die besten in der Anzahl
der releasten Games und Sales?” Um dieser Fragestellung auf den Grund
zugehen müssen wir zuerst einmal die Daten der Tabelle vgsales mithilfe
der Funktion group_by(Year) anhand der Jahre Zusammenfassen.
Nun erhalten wir eine nach den Jahren zusammengefasste Tabelle deren
Einträge wir mit der Funktion dplyr::summarize(Anzahl =n())
abzählen und als Wert Anzahl abspeichern. Aufgrund der für diese analyse
Fehlerhaften Daten verwenden wir noch die Funktion filter() um
alle fehlenden Jahreseinträge sowie die Jahre 2020 und 2017
herauszufiltern. Letztere Jahre sind daher fehlerhaft, da der Datensatz
2016 erstellt wurde. Diese Daten speichern wir als data.frame
in der Variable grouped ab. Im folgenden verwenden wir
ebenjenes data.frame um nur die Einträge Jahr und Anzahl zu selektieren
und in der Variable filtered abzuspeichern. Die erhaltene
Tabelle hat nun zwei Spalten: Jahr und Anzahl. Desweiteren erstellen wir
zwei Weitere Variablen ax und ay welche beide eine
Liste mit nur einem Attribut sind: “Title”. Nun verwenden wir
plot_ly() um mithilfe der type = ‘scatter’ und
mode = ‘lines’ Parameter ein Liniendiagramm zu erstellen.
Außerdem nutzen wir die layout() funktion um einen titel zu
erstellen, sowie mithilfe unsere beiden Variablen ax und ay die Achsen
zu beschriften.
grouped <- vgsales %>%
group_by(Year) %>%
dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
filtered <- grouped %>% select(Year,Anzahl)
ax <- list(
title = "Year"
)
ay <- list(
title = "Amount"
)
filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>%
layout(title="Game Amount from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Betrachten wir einmal das entstandene Diagramm. Zwischen 1980 und
1993 sind hier kaum unterschiede festzustellen und die Schwankungen
können aufgrund der geringen Zahl der Veröffentlichungen (zwischen 14
und 49) vernachlässigt werden.Ab 1993 können wir dann eine stetiges
Wachstum feststellen welches 1998 vorerst den höchstwert erreicht. In
den Jahren 1999 und 2000 geht die Anzahl erst einmal leicht zurück bevor
sich der Wert bis 2002 von 349 auf 829 mehr als verdoppelt. Bis 2004 ist
wiederum ein leichter Rückgang festzustellen auf welchem ein Stetiges
Wachstum zum Höchstwert von 1428 (2008) sowie 1431 (2009) folgt. Danach
folgt ein extremer und mit unterbrechung von 2014 (582) und 2015 (614)
stetiger Rückgang in den Releasezahlen auf einen Stand von 344 im Jahr
2016.
Sehen wir uns diese Zahlen einmal genauer an kommt die Frage auf
Woran diese Extremen Zahlen in den veröffentlichungen zurückzuführen
sind? An diesem Punkt der Analyse können wir nur Spekulieren die Spitzen
könnten allerdings an den Veröffentlichungen großer, den Markt
bestimmenden Plattformen wie der PS2/3, der Xbox und den Platformen von
Nintendo wie Gamecube oder Wii zurückzuführen sein.
Hierzu aber später mehr.
Game Sales
Um dem zweiten Teil der Fragestellung auf den Grund gehen zu können
müssen wir erneut die Daten der Tabelle vgsales mithilfe der Funktion
group_by(Year) anhand der Jahre Zusammenfassen. Nun erhalten
wir wieder die nach den Jahren zusammengefasste Tabelle deren Einträge
wir mit der Funktion dplyr::summarize(gr_sum =
sum(Global_Sales)) zusammenfassen. Dem Aufmerksamen Leser wird
auffallen das hier ein kleiner aber feiner Unterschied zum vorherigen
Aufruf besteht. Statt Anzahl =n() nutzen wir hier gr_sum =
sum(Global_Sales). Diese Funktion summiert alle Werte der Spalte
Global_Sales auf und speichert den den Wert in die Spalte
gr_sum. Aufgrund der für diese analyse weiterhin Fehlerhaften
Daten verwenden wir erneut die Funktion filter() um alle
fehlenden Jahreseinträge sowie die Jahre 2020 und 2017 herauszufiltern.
Diese Daten speichern wir wieder als data.frame in der Variable
grouped ab. Im folgenden verwenden wir ebenjenes data.frame um
nur die Einträge Jahr und gr_sum zu selektieren und in der
Variable filtered abzuspeichern. Die erhaltene Tabelle hat nun
zwei Spalten: Jahr und gr_sum. Desweiteren erstellen wir erneut
die Variablen ax und ay. Nun verwenden wir
plot_ly() um mithilfe der type = ‘scatter’ und
mode = ‘lines’ Parameter ein Liniendiagramm zu erstellen.
Außerdem nutzen wir die layout() funktion um einen titel zu
erstellen, sowie mithilfe unsere beiden Variablen ax und ay die Achsen
zu beschriften.
grouped <- vgsales %>%
group_by(Year) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
filtered <- grouped %>% select(Year,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = " Game Sales per Year (in mio)"
)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>%
layout(title="Game Sales from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Betrachten wir nun das entstandene Diagramm fällt uns zuerst auf,
dass es dem vorherigen recht ähnlich sieht. Dies ist kaum verwunderlich
und stellt keinen nennenswerten Wissensgewinn da. Der wohl
Nenneswerteste unterschied ist das Fehlen des Anstiegs, welcher in der
Anzahl der Gamereleases zum Jahr 2015 festzustellen war. Durch den
direkten Vergleich ist dies allerdings ein guter Zeitpunkt um uns mit
unserer Zweiten These auseinanderzusetzen. “Werden heutzutage mehr
Spiele Releast und Verkauft als noch 1980?”. Diese sehen wir
aufjedenfall bestätigt obwohl Festzustellen ist, dass die besten Jahre
sowohl in verkäufen als auch in der Anzahl die Jahre 2008 und 2009
waren. Dies Wirft natürlich die Frage auf was der Grund für diesen
Verlauf ist und wäre ein Interessanter ansatz für eine weitere Arbeit.
Sales per Game
Die Frage die Wir allerdings beantworten können ist “Werden
neuere Spiele automatisch mehr Gekauft?”. Dafür kombinieren wir die
beiden bereits Verwendeten ansätze. Wir fassen wieder die daten mithilfe
von group_by(Year) anhand der Jahre Zusammen. Die erhaltene
Tabelle fassen wir wieder mit dplyr::summarize(gr_sum =
sum(Global_Sales)) zusammen. Diesmal nutzen wir jedoch eine
kombination aus sum(Global_Sales) und n(). Wir
addieren die Spalte Global_Sales, teilen dies durch die Anzahl
der Einträge und speichern den Wert in die Spalte gamesales
(gamesales = sum(Global_Sales)/n()). Danach filtern wir die
Daten erneut und speichern sie als data.frame in grouped ab.
Diesmal selektieren wie die Einträge der Spalte Jahr sowie
gamesales und speichern sie in der Variable filtered
ab. Zuletzt erstellen wir erneut die Variablen ax und
ay und verwenden plot_ly() um mithilfe der type =
‘scatter’ und mode = ‘lines’ Parameter ein Liniendiagramm
zu erstellen sowie die layout() funktion um einen titel zu
erstellen und mithilfe unsere beiden Variablen ax und ay die Achsen zu
beschriften.
grouped <- vgsales %>%
group_by(Year) %>%
dplyr::summarize(gamesales = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
filtered <- grouped %>% select(Year,gamesales)
ax <- list(
title = "Year"
)
ay <- list(
title = "Sales per Game"
)
filtered %>%
plot_ly(x = ~Year, y = ~gamesales, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>%
layout(title="Sales per Game from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Sahen sich die beiden Diagramme für Anzahl und Verkaufszahlen noch
recht ähnlich stellt sich hier ein deutlich unterschiedlicher Verlauf
da. Ist der Wert zwischen 1980 (1.26) und 1983 (0.98) noch relativ
gering steigt dieser Massiv für die Jahre 1984(3.59) und 1985(3.85)
bevor er 1986(1.76) und 1987(1.35) wieder absinkt. Genauso schnell wie
der wert abgesunken ist steigt er allerdings auch wieder auf 3.14(1988)
bevor er 1989 den Höchststand mit 4.32 erreicht. Danach sinkt der wieder
ab um sich nach einem kurzen ausschlag 1992 in den Jahren bis 2014 auf
einen relativ stetigen Wert Zwischen 0.5 und 0.7 einzupendeln erst 2015
und 2016 sinkt dieser unter 0.5. Diese Extremen ausschläge in den
Früheren Jahren lassen sich mit der Geringen anzahl der Spiele erklären.
Einzelne gute laufende Spiele machen hier noch einen Großteil des Markts
aus wohingegen sich neuere spiele, sowohl gegen eine Großzahl von
bereits etablierten Spiele als auch eine große Anzahl neuer Releases,
durchsetzen müssen.
Publisher Vergleich
Nun stellt sich die Frage ob sich neben bestimmten Platformen auch
bestimmte Entwickler/Publisher häufen. Hierbei gehen wir davon aus das
vermutlich Nintendo und EA die Liste anführen. Hierzu verwenden wir
wiederum sorted Bar-Charts und kürzen die Namen um die Begriffe
“Entertainment”, “Interactive”, “Game”, “Games” und “Studios” da dies
die Namen nur unnötig verlängert und Filtern Publisher mit Geringen
Anzahl an Game Releases.
Publisher
Amount
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n()) %>%
filter(Anzahl>100) %>% filter(Publisher!="Unknown")
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "Anzahl"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Publisher,Anzahl, .desc="true"),
y=~Anzahl,
name="Game Amount by Publisher"
,colors = myPalette) %>%
layout(title="Game Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Sales
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n(),sum(Global_Sales)) %>%
filter(Anzahl>100) %>%
rename(
Global_Sales = "sum(Global_Sales)"
)
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "Global Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
y=~Global_Sales,
name="Sales Amount by Publisher"
,colors = myPalette) %>%
layout(title="Sales Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Auffällig ist hier die diskrepanz zwischen Anzahl der Spielereleases
und Anzahl der Spieleverkäufe. Im gegensatz zu der Anzahl der Spiele
(bei dem Nintendo nur auf platz 6 Sitz) dominiert Nintendo im anzahl der
Sales.
Nun stellt sich wieder einmal die Frage ob sich dies in Bestimmten
teilen der Welt unterscheidet und hierzu verwenden wir wiederum die
SortedBar/Piechart kombo und die bereits genannten Filter
Publisher Ranking nach Region
Publisher Ranking nach Region
Balkendiagramme
Europa
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n(),sum(EU_Sales)) %>%
filter(Anzahl>100) %>%
rename(
Global_Sales = "sum(EU_Sales)"
)
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "EU Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
y=~Global_Sales,
name="EU Sales Amount by Publisher"
,colors = myPalette) %>%
layout(title="EU Sales Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Nord Amerika
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n(),sum(NA_Sales)) %>%
filter(Anzahl>100) %>%
rename(
Global_Sales = "sum(NA_Sales)"
)
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "NA Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
y=~Global_Sales,
name="NA Sales Amount by Publisher"
,colors = myPalette) %>%
layout(title="NA Sales Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Japan
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n(),sum(JP_Sales)) %>%
filter(Anzahl>100) %>%
rename(
Global_Sales = "sum(JP_Sales)"
)
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "JP Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
y=~Global_Sales,
name="JP Sales Amount by Publisher"
,colors = myPalette) %>%
layout(title="JP Sales Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Kreisdiagramme
Europa
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n(),sum(EU_Sales)) %>%
filter(Anzahl>100) %>%
rename(
Global_Sales = "sum(EU_Sales)"
)
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "EU Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Publisher,
name="EU Sales Amount by Publisher"
,colors = myPalette) %>%
layout(title="EU Sales Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Nord-Amerika
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n(),sum(NA_Sales)) %>%
filter(Anzahl>100) %>%
rename(
Global_Sales = "sum(NA_Sales)"
)
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "NA Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Publisher,textinfo='label+percent',
name="NA Sales Amount by Publisher"
,colors = myPalette) %>%
layout(title="NA Sales Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Japan
grouped <- vgsales %>%
group_by(Publisher) %>%
summarize(Anzahl =n(),sum(JP_Sales)) %>%
filter(Anzahl>100) %>%
rename(
Global_Sales = "sum(JP_Sales)"
)
PublisherSales <- vgsales %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)
ax <- list(
title = "Publisher"
)
ay <- list(
title = "JP Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Publisher,
name="JP Sales Amount by Publisher"
,colors = myPalette) %>%
layout(title="JP Sales Amount by Publisher",
xaxis = ax,
yaxis = ay
)
Zwischen EU und US lassen sich hier kaum Unterschiede feststellen in
Japan hingegen ist eine verschiebung zu erkennen. Japanische Publisher
führen hierbei die Liste an und drängen andere große unternehmen von den
Top spots.
Genreverteilung der Videospiele nach Anzahl
Nun schauen wir uns die Genreverteilung von Videospielen an. Hierzu
verwenden wir wiederum die Altbekannte sorted Bar/Pie-Chart kombo.
Genre Amount
Balken Diagramm
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(Anzahl =n())
grouped$Anzahl<-as_vector(grouped$Anzahl)
ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Genre <- as_factor(ordered$Genre)
ax <- list(
title = "Genre"
)
ay <- list(
title = "Anzahl"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Genre,Anzahl, .desc="true"),
y=~Anzahl,
name="Amount by Genre"
,colors = myPalette) %>%
layout(title="Amount by Genre",
xaxis = ax,
yaxis = ay
)
NA
Kreis Diagramm
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(Anzahl =n())
grouped$Anzahl<-as_vector(grouped$Anzahl)
ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Genre <- as_factor(ordered$Genre)
ax <- list(
title = "Genre"
)
ay <- list(
title = "Anzahl"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Anzahl,labels=~Genre,
name="Amount by Genre"
,colors = myPalette) %>%
layout(title="Amount by Genre",
xaxis = ax,
yaxis = ay
)
Hierbei ist zu erkennen das Action und Sports ein Großteil (34%) der
Genres ausmachen. Die Frage ist jedoch wie sind die Verkäufe verteilt
und beeinflusst die anzahl der Games pro Genre irgendwie die
Verkaufszahlen?
Sales Amount
Balken Diagramm
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
y=~Global_Sales,
name="Sales by Genre"
,colors = myPalette) %>%
layout(title="Sales by Genre",
xaxis = ax,
yaxis = ay
)
NA
Kreis Diagramm
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Genre,
name="Sales by Genre"
,colors = myPalette) %>%
layout(title="Sales by Genre",
xaxis = ax,
yaxis = ay
)
Hierbei erkennen wir das es einige Unterschiede gibt Action und
sports machen jedoch weiterhin einen Grosteil des Markts aus.
Nun schauen wir uns die Unterscheide in den Regionen an.
Regionale Unterschiede der Genres
SalesbyGenre
Balkendiagramme
Europa
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(EU_Sales)) %>%
rename(
Global_Sales = "sum(EU_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
y=~Global_Sales,
name="Sales by Genre (EU)"
,colors = myPalette) %>%
layout(title="Sales by Genre (EU)",
xaxis = ax,
yaxis = ay
)
Nord-Amerika
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(NA_Sales)) %>%
rename(
Global_Sales = "sum(NA_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
y=~Global_Sales,
name="Sales by Genre (NA)"
,colors = myPalette) %>%
layout(title="Sales by Genre (NA)",
xaxis = ax,
yaxis = ay
)
Japan
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(JP_Sales)) %>%
rename(
Global_Sales = "sum(JP_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales"
)
ordered%>%
plot_ly() %>%
add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
y=~Global_Sales,
name="Sales by Genre (JP)" ,colors = myPalette) %>%
layout(title="Sales by Genre (JP)",
xaxis = ax,
yaxis = ay
)
NA
Kreisdiagramme
Europa
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(EU_Sales)) %>%
rename(
Global_Sales = "sum(EU_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Genre,
name="Sales by Genre (EU)" ,colors = myPalette) %>%
layout(title="Sales by Genre (EU)",
xaxis = ax,
yaxis = ay
)
Nord-Amerika
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(NA_Sales)) %>%
rename(
Global_Sales = "sum(NA_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales (in mio)"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Genre,
name="Sales by Genre (NA)",colors = myPalette) %>%
layout(title="Sales by Genre (NA)",
xaxis = ax,
yaxis = ay
)
Japan
grouped <- vgsales %>%
group_by(Genre) %>%
summarize(sum(JP_Sales)) %>%
rename(
Global_Sales = "sum(JP_Sales)"
)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales"
)
ordered%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Genre,
name="Sales by Genre (JP)" ,colors = myPalette) %>%
layout(title="Sales by Genre (JP)",
xaxis = ax,
yaxis = ay
)
Hierbei erkennen wir wieder einmal das US und EU recht ähnlich sind
wohingegen Japan ein gänzlich anderes Genreshema erkennen lässt. In
Japan dominiert Role-Playing welches sich in EU und US nur auf platz 7
befindet.
Nun schauen wir uns die Genreentwicklung über die Jahre an. Hierzu
verwenden wir LinePlots.
Genreentwicklung im laufe der Jahre nach anzahl
Genre Amount per Year
Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
title = "Year"
)
ay <- list(
title = "Anzahl"
)
filtered %>%
plot_ly() %>%
add_lines(x=~Year,
y=~Anzahl, color=~Genre,colors = myPalette)
NA
Filled Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
title = "Year"
)
ay <- list(
title = "Anzahl"
)
filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette)%>%
layout(title="Amount by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Stacked Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
title = "Year"
)
ay <- list(
title = "Anzahl"
)
filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre, colors = myPalette)%>%
layout(title="Amount by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Genreshift %
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
title = "Year"
)
ay <- list(
title = "Percent %"
)
filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre ,colors = myPalette)%>%
layout(title="Marketamount genreshift in % from 1980-2016",
xaxis = ax,
yaxis = ay
)
Hierbei zu erkennen ist Obwohl die Anzahl der Jährlichen
Spielereleases über die Jahre hinweg stetig wächst bleiben die Meisten
Genres ähnlich viel vertreten. Auffällig sind hierbei Strategy-Games die
erst 1991 das erste mal auftretem Seitdem obwohl sie Leicht an
Marketshare verlieren grob gleich bleiben. Außerdem sind Action Games
die Spiele mit der wohl größten volatilität. Sind es 1982 noch fast 50%
der Gamereleases fällt deren aufkommen 1084 schon auf nur noch knapp 10%
ab und 1986 steigt der Wert wieder auf fast 30%. Dieser Trend setzt sich
fort bis 1996 ab welchem Zeitpunkt sich Action Games von 3.6% über die
Jahre bis 2016 bis 35% entwickeln.
Genreentwicklung im laufe der Jahre nach Verkaufszahlen
Schauen wir uns an wie sich die verkäufe entwickelt haben.
Sales Amount per Year
Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Global_Sales"
)
filtered %>%
plot_ly() %>%
add_lines(x=~Year,
y=~gr_sum, color=~Genre ,colors = myPalette) %>%
layout(title="Sales by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Filled Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Global_Sales"
)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette) %>%
layout(title="Sales by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Stacked Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Global_Sales"
)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre ,colors = myPalette)%>%
layout(title="Sales by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
Genreshift %
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Percent %"
)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre ,colors = myPalette)%>%
layout(title="Marketshare genreshift in % from 1980-2016",
xaxis = ax,
yaxis = ay
)
Wie zu erwarten lässt sich hier ein Großer overlap zu den Anzahl der
Gamereleases feststellen.
Genreentwicklung im laufe der Jahre nach Verkaufszahlen pro
Spiel
Nun stellt sich die Frage hab sich die Verkäufe ähnlich der anzahl
der GameReleases entwickelt?
Sales per Game per Year
Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Sales per Game"
)
filtered %>%
plot_ly() %>%
add_lines(x=~Year,
y=~gr_sum, color=~Genre ,colors = myPalette) %>%
layout(title="Sales per Game by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Filled Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Sales per Game"
)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette) %>%
layout(title="Sales per Game by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
NA
Stacked Lines
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Sales per Game"
)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre, colors = myPalette)%>%
layout(title="Sales per Game by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
Genreshift %
grouped <- vgsales %>%
group_by(Year, Genre) %>%
dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
title = "Year"
)
ay <- list(
title = "Percent %"
)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre, colors = myPalette)%>%
layout(title="Marketshare in Sales per Game by Genre from 1980-2016",
xaxis = ax,
yaxis = ay
)
Auch hier ist wie erwartet die Entwicklung Prozentual ähnlich sind.
Auffällig ist jedoch das Shooter trotz ihrer geringen Vertretung in der
Prozentualen Verteilung 1984 sowie 2014,2015 und 2016 die Nase Vorne
haben. Platform Games haben 1985,1988 und 1990 die Nase Vorne. Die
Hochzeit der Puzzle Games sind unangefochten 1988 mit dem
Weltweitbekannten und auf Platz 6 der meistverkauften videospiele:
Tetris. Ein genauerer vergleich der Ausschläge mit den dementsprechenden
Videospielen wäre hier wünschenswert würde aber das Ausmaß dieser Arbeit
sprengen.
Nun stellt sich die Frage wie es mit Genres pro publisher aussieht?
Gibt es hier Publisher die verschiedene Genres bevorzugen bzw. deren
Bestseller sich in bestimmten Genres Tummeln?
Hierzu verwenden wir ein stacked Bar-Plot. Dazu filtern wir die top
10 Publishern aka Publisher mit min 116 mio in Sales. Dies entfernt
natürlich einiges an Information allerdings geht sonst einiges an
Übersichtlichkeit verloren. Zusätzlich werden erneut die Worte
“Entertainment”, “Interactive”, “Game”, “Games” und “Studios”
entfernt.
Genreverteilung nach Publisher
Genre by Publisher
Sales
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
)
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
PublisherSales <- grouped %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
grouped$Publisher <-str_remove_all(grouped$Publisher, "Entertainment")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Interactive")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Studios")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Games")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Game")
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales"
)
grouped%>%
plot_ly(x=~Publisher,
y=~Global_Sales,
type='bar',
color=~Genre, colors = myPalette) %>%
layout(title="Sales by Genre By Publisher",
xaxis = ax,
yaxis = ay,
barmode = 'stack'
)
NA
NA
Amount
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(Anzahl =n(),sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
)
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
PublisherSales <- grouped %>%
group_by(Publisher) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>% filter(Global_Sales>300)
grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
grouped$Publisher <-str_remove_all(grouped$Publisher, "Entertainment")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Interactive")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Studios")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Games")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Game")
ax <- list(
title = "Genre"
)
ay <- list(
title = "Amount"
)
grouped%>%
plot_ly(x=~Publisher,
y=~Anzahl,
type='bar',
color=~Genre ,colors = myPalette) %>%
layout(title="Amount by Genre By Publisher",
xaxis = ax,
yaxis = ay,
barmode = 'stack'
)
NA
NA
NA
Bei dem vergleich der Werte ist hier zu bemerken, dass die meisten
Publisher Hierbei sich mit der Anzahl der Spiele und den Sales gut
abdecken. Die auffälligsten diskrepanzen sind hierbei EA mit dem Sports
Genre und ihren järlich releasten Spielen FiFa/NBA2k etc. sowie Nintendo
mit der Platformreihe Super Mario. Schauen wir uns diese Beiden Firmen
Noch einmal im Detail an.
Hierzu verwenden wir wieder die Bar/Pie chart Combo die uns Bereits
aus vorderen Teilen der Ausarbeitung bekannt sind.
Genreverteilung für Publisher Electronic Arts
Genre für Electronic Arts
Balkendiagramme
Sales
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>%
filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales"
)
grouped%>%
plot_ly() %>% add_bars(x=~Genre,
y=~Global_Sales,
color=~Genre ,colors = myPalette) %>%
layout(title="Sales by Genre for Electronic Arts",
xaxis = ax,
yaxis = ay,
barmode = 'stack'
)
NA
Amount
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(Anzahl =n()) %>%
filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
ax <- list(
title = "Genre"
)
ay <- list(
title = "Amount"
)
grouped%>%
plot_ly() %>% add_bars(x=~Genre,
y=~Anzahl,
color=~Genre ,colors = myPalette) %>%
layout(title="Amount by Genre for Electronic Arts ",
xaxis = ax,
yaxis = ay,
barmode = 'stack'
)
NA
Kreisdiagramme
Sales
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>%
filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales"
)
grouped%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Genre,textinfo='label+percent',sort = FALSE,
name="Sales by Genre for Electronic Arts" ,colors = myPalette) %>%
layout(title="Sales by Genre for Electronic Arts",
xaxis = ax,
yaxis = ay
)
NA
NA
Amount
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(Anzahl =n()) %>%
filter(Publisher == "Electronic Arts")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
ax <- list(
title = "Genre"
)
ay <- list(
title = "Amount"
)
grouped%>%
plot_ly() %>%
add_pie(values =~Anzahl,labels=~Genre,textinfo='label+percent',sort = FALSE,
name="Amount by Genre for Electronic Arts" ,colors = myPalette) %>%
layout(title="Amount by Genre for Electronic Arts",
xaxis = ax,
yaxis = ay
)
NA
Schauen wir uns EA hier im Detail an fällt allerdings auf das die
Diskrepanz zwischen Sales und Anzahl der Gamereleases für EA bei Sports
gar nicht so groß ist (41.5% vs 43.2%). Die größeren diskrepanzen sind
hier Shooter welches nur 10% der Gamereleases sind aber gut 15% der
Sales und Action mit 13.5% der Gamereleases und 10.4% der Sales.
Genreverteilung für Nintendo
Schauen wir uns nun Nintendo an.
Genre für Nintendo
Balkendiagramme
Sales
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>%
filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales"
)
grouped%>%
plot_ly() %>% add_bars(x=~Genre,
y=~Global_Sales,
color=~Genre ,colors = myPalette) %>%
layout(title="Sales by Genre for Nintendo",
xaxis = ax,
yaxis = ay,
barmode = 'stack'
)
NA
NA
Amount
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(Anzahl =n()) %>%
filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
Warning: Unknown or uninitialised column: `Global_Sales`.
ax <- list(
title = "Genre"
)
ay <- list(
title = "Amount"
)
grouped%>%
plot_ly() %>% add_bars(x=~Genre,
y=~Anzahl,
color=~Genre ,colors = myPalette) %>%
layout(title="Amount by Genre for Nintendo",
xaxis = ax,
yaxis = ay,
barmode = 'stack'
)
NA
Kreisdiagramme
Sales
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(sum(Global_Sales)) %>%
rename(
Global_Sales = "sum(Global_Sales)"
) %>%
filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ax <- list(
title = "Genre"
)
ay <- list(
title = "Sales"
)
grouped%>%
plot_ly() %>%
add_pie(values =~Global_Sales,labels=~Genre,textinfo='label+percent',sort = FALSE,
name="Sales by Genre for Nintendo" ,colors = myPalette) %>%
layout(title="Sales by Genre for Nintendo",
xaxis = ax,
yaxis = ay
)
NA
NA
Amount
grouped <- vgsales %>%
group_by(Publisher,Genre) %>%
summarize(Anzahl =n()) %>%
filter(Publisher == "Nintendo")
`summarise()` has grouped output by 'Publisher'. You can override using the `.groups` argument.
ax <- list(
title = "Genre"
)
ay <- list(
title = "Amount"
)
grouped%>%
plot_ly() %>%
add_pie(values =~Anzahl,labels=~Genre,textinfo='label+percent',sort = FALSE,
name="Amount by Genre for Nintendo" ,colors = myPalette) %>%
layout(title="Amount by Genre for Nintendo",
xaxis = ax,
yaxis = ay
)
NA
Bei Nintendo zu erkennen ist hier, dass Platform spiele ein
Kassenchlager sind. Nehmen diese nur 16% der spielereleases ein so
bringen sie dennoch 24% der Sales ein. Gleiches Gilt für Sport games. 8%
gegenüber 12%. Action (11% vs 7%), Misc (14% vs 10%) und Puzzle Games
(10.5% vs 7%) sind jedoch nicht so erfolgreich.
Ausblick in die Zukunft
Ein Vergleich der Ausschläge mit den dementsprechenden
Videospielen.
Eine genaue Analyse der Gamesales pro jahr (aka tetrist 1950 30 mal
testris 2015 300000 mal) geben die daten nicht her.
eine anylse der Coronapandemie veränderungen (geben die daten nicht
her)
Platformanalyse: Verkauften Spiele pro Spiel pro platform
Aufgetretene Probleme
Colorbrewer wird nicht in jeder Grafik akzeptiert
Sales pro Game analyse rechnet nicht spiele pro platform zusammen
Mobilegames fehlen im datensatz umfast nur 16k game von weltweit mehr
als 3.3 mio https://www.statista.com/statistics/293304/number-video-gamers/#:~:text=In%20total%2C%20there%20were%20an,billion%20gamers%20across%20the%20globe.
oft doppelter code durch verwendung in mehreren Diagrammen mit nur
leichten änderungen
Platformanalyse nach region Vergleich in anzahl der Spiele nicht
möglich da herkunftsland des spiels nicht klar
Regionaler vergleich aufgrund von unterschiedlichen enwohner zahlen
nur prozentual nicht absolut möglich
LS0tDQp0aXRsZTogIlZpZGVvIEdhbWUgU2FsZXMiDQpvdXRwdXQ6IA0KICAgDQogICBodG1sX2RvY3VtZW50IDogDQogICAgICBpbmNsdWRlczoNCiAgICAgICAgYWZ0ZXJfYm9keTogZm9vdGVyLmh0bWwNCiAgICAgIHRoZW1lOiBjb3Ntbw0KICAgICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICBodG1sX25vdGVib29rIDogDQogICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICAgIGluY2x1ZGVzOg0KICAgICAgICBhZnRlcl9ib2R5OiBmb290ZXIuaHRtbA0KICAgICAgdGhlbWU6IGNvc21vDQotLS0NCjxjZW50ZXI+IVtdKFZpZGVvZ2FtZXMucG5nKSA8L2NlbnRlcj4NCjxjZW50ZXI+IA0KIyBGbG9yaWFuIFJlaWNobGUgDQo8L2NlbnRlcj4NCioqKg0KDQojIyMgKipBbmdhYmVuIHp1IGRlbiBEYXRlbioqDQpEYXMgdmVyd2VuZGV0ZSBEYXRhc2V0IGRlcyBQcm9qZWt0czogaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9ncmVnb3J1dC92aWRlb2dhbWVzYWxlcyAgIA0KRGllcyBiZXN0ZWh0IGF1cyBkZW4gRGF0ZW4gdm9uIGh0dHBzOi8vd3d3LnZnY2hhcnR6LmNvbS8gZsO8ciBkaWUgSmFocmUgMTk4MCBiaXMgMjAxNiB1bmQgdW1mYXNzdCBkaWUgRm9sZ2VuZGVuIFNwYWx0ZW4gYnp3LkRhdGVuLg0KDQoqIFJhbmsgLSBEaWUgUGxhdHppZXJ1bmcgZGVzIFNwaWVscyBuYWNoIEFuemFobCBkZXIgVmVya8OkdWZlbg0KKiBOYW1lIC0gRGVyIE5hbWUgZGVzIFNwaWVscw0KKiBQbGF0Zm9ybSAtIERpZSBQbGF0Zm9ybSBhdWYgZGVyIGRhcyBTcGllbCB2ZXLDtmZmZW50bGljaHQgd3VyZGUgKHouQi4gUEMsUFM0LCBldGMuKQ0KKiBZZWFyIC0gRGFzIEphaHIgZGVyIFZlcsO2ZmZlbnRsaWNodW5nIGRlcyBTcGllbHMNCiogR2VucmUgLSBEYXMgR2VucmUgZGVzIFNwaWVscyAoei5CLiBTcG9ydCxBY3Rpb24sIFB1enpsZSkNCiogUHVibGlzaGVyIC0gRGVyIFB1Ymxpc2hlciBkZXMgU3BpZWxzDQoqIE5BX1NhbGVzIC0gRGllIEFuemFobCBkZXIgVmVya8OkdWZlIGluIE5vcmQtQW1lcmlrYSAoaW4gbWlsbGlvbmVuKQ0KKiBFVV9TYWxlcyAtIERpZSBBbnphaGwgZGVyIFZlcmvDpHVmZSBpbiBFdXJvcGEgKGluIG1pbGxpb25lbikNCiogSlBfU2FsZXMgLSBEaWUgQW56YWhsIGRlciBWZXJrw6R1ZmUgaW4gSmFwYW4gKGluIG1pbGxpb25lbikNCiogT3RoZXJfU2FsZXMgLSBEaWUgQW56YWhsIGRlciBWZXJrw6R1ZmUgaW0gUmVzdCBkZXIgV2VsdCAoaW4gbWlsbGlvbmVuKQ0KKiBHbG9iYWxfU2FsZXMgLSBEaWUgQW56YWhsIGRlciBWZXJrw6R1ZmUgV2VsdHdlaXQgKGluIG1pbGxpb25lbikNCg0KKioqDQoNCiMjIyAqKkluaGFsdHN2ZXJ6ZWljaG5pcyoqDQoNCg0KMS4gUmVsZWFzZWFuYWx5c2UNCiAgICArIFtuYWNoIEFuemFobF0oI1ZpZGVvR2FtZVJlbGVhc2VzKQ0KICAgICsgW25hY2ggU2FsZXNdKCNWaWRlb0dhbWVSZWxlYXNlcykNCiAgICArIFtuYWNoIFNhbGVzIHBybyBHYW1lXSgjVmlkZW9HYW1lUmVsZWFzZXMpDQogICAgDQoyLiBQbGF0Zm9ybWFuYWx5c2UNCiAgICArIFtHbG9iYWxdKCNQbGF0Zm9ybWFuYWx5c2UpDQogICAgKyBbbmFjaCBSZWdpb25dKCNQbGF0Zm9ybVJhbmtpbmdCeVJlZ2lvbikNCiAgICArIFtWZXJrYXVmc3pobGVudHdpY2tsdW5nIGltIGxhdWZlIGRlciBKYWhyZV0oI1NhbGVzUGVyUGxhdGZvcm0pDQogICAgDQozLiBQdWJsaXNoZXJhbmFseXNlIA0KICAgICsgW0dsb2JhbF0oI1B1Ymxpc2hlclJlbGVhc2VzKQ0KICAgICsgW25hY2ggUmVnaW9uXSgjUHVibGlzaGVyUmFua2luZ2J5UmVnaW9uKQ0KICAgIA0KNC4gR2VucmVhbmFseXNlDQogICAgKyBbR2xvYmFsXSgjR2VucmVBbW91bnRHbG9iYWwpDQogICAgKyBbbmFjaCBSZWdpb25dKCNHZW5yZUFtb3VudEJ5UmVnaW9uKQ0KICAgIA0KNS4gR2VucmV2ZXJ0ZWlsdW5nIHBybyBKYWhyDQogICAgKyBbbmFjaCBBbnphaGxdKCNHZW5yZUFtb3VudFBlclllYXIpDQogICAgKyBbbmFjaCBWZXJrYXVmc3phaGxlbl0oI0dlbnJlU2FsZXNQZXJZZWFyKQ0KICAgICsgW25hY2ggVmVya2F1ZnN6YWhsZW4gcHJvIFNwaWVsXSgjR2VucmVTYWxlc1BlckdhbWVQZXJZZWFyKQ0KICAgIA0KNi4gUHVibGlzaGVyIEdlbnJlcw0KICAgICsgW2bDvHIgZGllIFRvcCBQdWJsaXNoZXJdKCNHZW5yZUJ5UHVibGlzaGVyR2xvYmFsKQ0KICAgICsgW0RldGFpbGFuYWx5c2UgRWxlY3Ryb25pYyBBcnRzXSgjR2VucmVCeVB1Ymxpc2hlckVBKQ0KICAgICsgW0RldGFpbGFuYWx5c2UgTmludGVuZG9dKCNHZW5yZUJ5UHVibGlzaGVyTmludGVuZG8pDQogICAgDQo3LiBLcml0aXNjaGVyIFLDvGNrYmxpY2sNCiAgICArIFtBdXNibGljayBpbiBkaWUgWnVrdW5mdF0oI0F1c2JsaWNrSW5EaWVadWt1bmZ0KQ0KICAgICsgW0F1ZmdldHJldGVuZSBQcm9ibGVtZV0oI0F1ZmdldHJldGVuZVByb2JsZW1lKQ0KDQoqKioNCiMjIyBUaGVzZW4NCg0KQmV2b3Igd2lyIG1pdCBkZXIgQW5hbHlzZSBkZXIgRGF0ZW4gYmVnaW5uZW4ga8O2bm5lbiBTdGVsbGVuIHdpciBlcnN0bWFsIGVpbiBwYWFyIFRoZXNlbiBiencuIEZyYWdlc3RlbGx1bmdlbiBhdWYgZGllIHdpciBpbSBsYXVmZSBkZXMgUHJvamVrdHMgaGludGVyZnJhZ2VuIGJ6dyBiZWFudHdvcnRlbiB3b2xsZW4uICANCg0KKiBXZWxjaGUgSmFocmUgc2luZCBkaWUgYmVzdGVuIGluIGRlciBBbnphaGwgZGVyIHJlbGVhc3RlbiBHYW1lcyB1bmQgU2FsZXM/ICBbQW50d29ydF0oI1ZpZGVvR2FtZVJlbGVhc2VzKQ0KKiBXZXJkZW4gaGV1dHp1dGFnZSBtZWhyIFNwaWVsZSBSZWxlYXN0IHVuZCBWZXJrYXVmdCBhbHMgbm9jaCAxOTgwPyBbQW50d29ydF0oI1ZpZGVvR2FtZVJlbGVhc2VzKQ0KKiBXZWxjaGUgSmFocmUgc2luZCBkaWUgYmVzdGVuIGluIEFuemFobCBTYWxlcyBwcm8gR2FtZT8gV2VyZGVuIG5ldWVyZSBTcGllbGUgYXV0b21hdGlzY2ggbWVociBHZWthdWZ0PyBbQW50d29ydF0oI1ZpZGVvR2FtZVJlbGVhc2VzKQ0KDQoqIFdlbGNoZSBQbGF0dGZvcm0gaXN0IGRpZSBiZXN0ZSBpbiBBbnphaGwgdmVya8OkdWZlbj8gV2VsY2hlIGluIEFuemFobCBkZXIgR2FtZSBSZWxlYXNlcz8gW0FudHdvcnRdKCNQbGF0Zm9ybWFuYWx5c2UpDQoqIEhhYmVuIMOEbHRlcmUgUGxhdGZvcm1lbiBBdXRvbWF0aXNjaCBtZWhyIFNwaWVsZSB1bmQgVmVya8OkdWZlPyBbQW50d29ydF0oI1BsYXRmb3JtUmFua2luZ0dsb2JhbF9FbmQpDQoqIEZhdm9yaXNpZXJlbiB2ZXJzY2hpZWRlbmUgUmVnaW9uZW4gdmVyc2NoaWVkZW5lIFBsYXRmb3JtZW4/IFZlcmthdWZlbiBkaWUgUmVnaW9uZW5oZWltaXNjaGVuIFBsYXRmb3JtZW4gYXV0b21hdGlzY2ggYXVjaCBkaWUgbWVpc3RlbiBTcGllbGU/IFtBbnR3b3J0XSgjUGxhdGZvcm1SYW5raW5nQnlSZWdpb24pDQoqIFdpZSBFbnR3aWNrZWxuIHNpY2ggZGllIFZlcmvDpHVmZSBwcm8gUGxhdGZvcm0gaW0gbGF1ZmUgZGVyIEphaHJlPyBIYWJlbiBQbGF0Zm9ybWVuIGt1cnogbmFjaCBSZWxlYXNlIGRlbiBncsO2w590ZW4gIkh5cGUiPyBbQW50d29ydF0oI1NhbGVzUGVyUGxhdGZvcm0pDQoNCiogQmVzdGltbXRlIFB1Ymxpc2hlciBow6R1ZmVuIHNpY2ggaW4gQW56YWhsIGRlciBTcGllbGUgdW5kIGRlciBWZXJrw6R1ZmVuICh6LkIuIE5pbnRlbmRvLCBFQSwgQWN0aXZpc2lvbiBCbGl6emFyZCkgW0FudHdvcnRdKCNQdWJsaXNoZXJSZWxlYXNlcykgIA0KKiBHaWJ0IGVzIHJlZ2lvbmFsZSBVbnRlcnNjaGllZGUgaW4gZGVuIFB1Ymxpc2hlcm4/IFdlcmRlbiBSZWdpb25lbmludGVybmUgUHVibGlzaGVyIEZhdm9yaXRpc2llcnQ/IFtBbnR3b3J0XSgjUHVibGlzaGVyUmFua2luZ2J5UmVnaW9uKQ0KDQoqIFdpZSBzaW5kIGRpZSBHZW5yZXMgZGVyIFNwaWVsZSB2ZXJ0ZWlsdD8gSMOkdWZlbiBzaWNoIGJlc3RpbW10ZSBHZW5yZXMgYmVpIEFuemFobCB1bmQgVmVya2F1ZnN6YWhsZW4/IEdpYnQgZXMgR2VucmVzIGRpZSBiZXNzZXIvc2NobGVjaHRlciBQZXJmb3JtZW4gYWxzIHNpZSBzb2xsdGVuPyBbQW50d29ydF0oI0dlbnJlQW1vdW50R2xvYmFsKSAgIA0KKiBHaWJ0IGVzIHJlZ2lvbmFsZSBVbnRlcnNjaGllZGUgaW4gZGVuIEdlbnJlcz8gKEdpYnQgZXMgUmVnaW9uZW4gZGllIFNwZXppZmlzY2hlIEdlbnJlcyBGYXZvcmlzaWVyZW4gd2VsY2hlIGluIGFuZGVyZW4gUmVnaW9uZW4gbnVyIGVpbmUgZ2VyaW5nZSBSb2xsZSBzcGllbHQ/KSBbQW50d29ydF0oI0dlbnJlQW1vdW50QnlSZWdpb24pDQoNCiogV2llIGhhYmVuIHNpY2ggZGllIEdlbnJlcyDDvGJlciBkaWUgSmFocmUgZW50d2lja2VsdD8gW0FudHdvcnRdKCNHZW5yZUFtb3VudFBlclllYXIpDQoqIEdpYnQgZXMgR2VucmVzIGRpZSBtYWwgZ3Jvw59lbiBFaW5mbHVzcyBoYXR0ZW4gdW5kIG51biBCZWRldXR1bmdzbG9zIHNpbmQ/IFtBbnR3b3J0XSgjR2VucmVTYWxlc1BlckdhbWVQZXJZZWFyKQ0KDQoqIEdpYnQgZXMgUHVibGlzaGVyIGRpZSBiZXN0aW1tdGUgR2VucmVzIGJldm9yenVnZW4gYnp3LiBQdWJsaXNoZXIgZGVyZW4gR2FtZXMgZWluZXMgYmVzdGltbXRlbiBHZW5yZXMgc2ljaCBiZXNvbmRlcnMgZ3V0IFZlcmthdWZlbj8gW0FudHdvcnRdKCNHZW5yZUJ5UHVibGlzaGVyR2xvYmFsKQ0KDQoNCioqKg0KDQojIyMgRGF0ZW4gdW5kIExpYnJhcnlzDQpOYWNoIGRlbSBWb3JzdGVsbGVuIGRlciBEYXRlbiB1bmQgZGVtIGF1ZnN0ZWxsZW4gZGVyIGluaXRpYWxlbiBUaGVzZW4ga8O2bm5lbiB3aXIgbnVuIG1pdCBkZW0gZWlubGVzZW4gZGVyIERhdGVuIGJlZ2lubmVuLiAgDQpadXPDpHR6bGljaCBlcnN0ZWxsZW4gd2lyIG5vY2ggZWluZSBGYXJicGFsZXR0ZSB1bmQgaW1wb3J0aWVyZW4gZGllIExpYnJhcnlzDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPVRSVUUsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZm9yY2F0cykNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShrbml0ciwgd2Fybi5jb25mbGljdHMgPSBGQUxTRSwgcXVpZXRseT1UUlVFKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KbGlicmFyeSh4dHMpDQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShkcGx5cikpDQpteVBhbGV0dGUgPC0gYnJld2VyLnBhbCgxMCwgIlBhaXJlZCIpDQp2Z3NhbGVzIDwtIHJlYWRfY3N2KCJ2Z3NhbGVzLmNzdiIpDQpgYGANCg0KKioqDQoNCg0KIyBWaWRlbyBHYW1lIFJlbGVhc2VzIHsjVmlkZW9HYW1lUmVsZWFzZXN9DQoNCg0KIyMgR2FtZSBSZWxlYXNlcyBvdmVyIHRoZSBZZWFycyB7LnRhYnNldH0NCiMjIyBHYW1lIEFtb3VudCB7I1ZpZGVvR2FtZVJlbGVhc2VzQW1vdW50fQ0KDQpVbnNlcmUgZXJzdGUgVGhlc2Ugd2FyICJXZWxjaGUgSmFocmUgc2luZCBkaWUgYmVzdGVuIGluIGRlciBBbnphaGwgZGVyIHJlbGVhc3RlbiBHYW1lcyB1bmQgU2FsZXM/IiBVbSBkaWVzZXIgRnJhZ2VzdGVsbHVuZyBhdWYgZGVuIEdydW5kIHp1Z2VoZW4gbcO8c3NlbiB3aXIgenVlcnN0IGVpbm1hbCBkaWUgRGF0ZW4gZGVyIFRhYmVsbGUgdmdzYWxlcyBtaXRoaWxmZSBkZXIgRnVua3Rpb24gKmdyb3VwX2J5KFllYXIpKiBhbmhhbmQgZGVyIEphaHJlIFp1c2FtbWVuZmFzc2VuLiBOdW4gZXJoYWx0ZW4gd2lyIGVpbmUgbmFjaCBkZW4gSmFocmVuIHp1c2FtbWVuZ2VmYXNzdGUgVGFiZWxsZSBkZXJlbiBFaW50csOkZ2Ugd2lyIG1pdCBkZXIgRnVua3Rpb24gICpkcGx5cjo6c3VtbWFyaXplKEFuemFobCA9bigpKSogYWJ6w6RobGVuIHVuZCBhbHMgV2VydCBBbnphaGwgYWJzcGVpY2hlcm4uIEF1ZmdydW5kIGRlciBmw7xyIGRpZXNlIGFuYWx5c2UgRmVobGVyaGFmdGVuIERhdGVuIHZlcndlbmRlbiB3aXIgbm9jaCBkaWUgRnVua3Rpb24gKmZpbHRlcigpKiB1bSBhbGxlIGZlaGxlbmRlbiBKYWhyZXNlaW50csOkZ2Ugc293aWUgZGllIEphaHJlIDIwMjAgdW5kIDIwMTcgaGVyYXVzenVmaWx0ZXJuLiBMZXR6dGVyZSBKYWhyZSBzaW5kIGRhaGVyIGZlaGxlcmhhZnQsIGRhIGRlciBEYXRlbnNhdHogMjAxNiBlcnN0ZWxsdCB3dXJkZS4gRGllc2UgRGF0ZW4gc3BlaWNoZXJuIHdpciBhbHMgKmRhdGEuZnJhbWUqIGluIGRlciBWYXJpYWJsZSAqZ3JvdXBlZCogYWIuIEltIGZvbGdlbmRlbiB2ZXJ3ZW5kZW4gd2lyIGViZW5qZW5lcyBkYXRhLmZyYW1lIHVtIG51ciBkaWUgRWludHLDpGdlIEphaHIgdW5kIEFuemFobCB6dSBzZWxla3RpZXJlbiB1bmQgaW4gZGVyIFZhcmlhYmxlICpmaWx0ZXJlZCogYWJ6dXNwZWljaGVybi4gRGllIGVyaGFsdGVuZSBUYWJlbGxlIGhhdCBudW4gendlaSBTcGFsdGVuOiBKYWhyIHVuZCBBbnphaGwuIERlc3dlaXRlcmVuIGVyc3RlbGxlbiB3aXIgendlaSBXZWl0ZXJlIFZhcmlhYmxlbiAqYXgqIHVuZCAqYXkqIHdlbGNoZSBiZWlkZSBlaW5lIExpc3RlIG1pdCBudXIgZWluZW0gQXR0cmlidXQgc2luZDogIlRpdGxlIi4gTnVuIHZlcndlbmRlbiB3aXIgKnBsb3RfbHkoKSogdW0gbWl0aGlsZmUgZGVyICp0eXBlID0gJ3NjYXR0ZXInKiB1bmQgKm1vZGUgPSAnbGluZXMnKiBQYXJhbWV0ZXIgZWluIExpbmllbmRpYWdyYW1tIHp1IGVyc3RlbGxlbi4gQXXDn2VyZGVtIG51dHplbiB3aXIgZGllICpsYXlvdXQoKSogZnVua3Rpb24gdW0gZWluZW4gdGl0ZWwgenUgZXJzdGVsbGVuLCBzb3dpZSBtaXRoaWxmZSB1bnNlcmUgYmVpZGVuIFZhcmlhYmxlbiBheCB1bmQgYXkgZGllIEFjaHNlbiB6dSBiZXNjaHJpZnRlbi4NCg0KYGBge3IgcGxvdChBbW91bnRCeVllYXIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShBbnphaGwgPW4oKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixBbnphaGwpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFtb3VudCINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfkFuemFobCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGZpbGwgPSAndG96ZXJveScgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkdhbWUgQW1vdW50IGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQpCZXRyYWNodGVuIHdpciBlaW5tYWwgZGFzIGVudHN0YW5kZW5lIERpYWdyYW1tLiBad2lzY2hlbiAxOTgwIHVuZCAxOTkzIHNpbmQgaGllciBrYXVtIHVudGVyc2NoaWVkZSBmZXN0enVzdGVsbGVuIHVuZCBkaWUgU2Nod2Fua3VuZ2VuIGvDtm5uZW4gYXVmZ3J1bmQgZGVyIGdlcmluZ2VuIFphaGwgZGVyIFZlcsO2ZmZlbnRsaWNodW5nZW4gKHp3aXNjaGVuIDE0IHVuZCA0OSkgdmVybmFjaGzDpHNzaWd0IHdlcmRlbi5BYiAxOTkzIGvDtm5uZW4gd2lyIGRhbm4gZWluZSBzdGV0aWdlcyBXYWNoc3R1bSBmZXN0c3RlbGxlbiB3ZWxjaGVzIDE5OTggdm9yZXJzdCBkZW4gaMO2Y2hzdHdlcnQgZXJyZWljaHQuIEluIGRlbiBKYWhyZW4gMTk5OSB1bmQgMjAwMCBnZWh0IGRpZSBBbnphaGwgZXJzdCBlaW5tYWwgbGVpY2h0IHp1csO8Y2sgYmV2b3Igc2ljaCBkZXIgV2VydCBiaXMgMjAwMiB2b24gMzQ5IGF1ZiA4MjkgbWVociBhbHMgdmVyZG9wcGVsdC4gQmlzIDIwMDQgaXN0IHdpZWRlcnVtIGVpbiBsZWljaHRlciBSw7xja2dhbmcgZmVzdHp1c3RlbGxlbiBhdWYgd2VsY2hlbSBlaW4gU3RldGlnZXMgV2FjaHN0dW0genVtIEjDtmNoc3R3ZXJ0IHZvbiAxNDI4ICgyMDA4KSBzb3dpZSAxNDMxICgyMDA5KSBmb2xndC4gRGFuYWNoIGZvbGd0IGVpbiBleHRyZW1lciB1bmQgbWl0IHVudGVyYnJlY2h1bmcgdm9uIDIwMTQgKDU4MikgdW5kIDIwMTUgKDYxNCkgc3RldGlnZXIgUsO8Y2tnYW5nIGluIGRlbiBSZWxlYXNlemFobGVuIGF1ZiBlaW5lbiBTdGFuZCB2b24gMzQ0IGltIEphaHIgMjAxNi4NCg0KU2VoZW4gd2lyIHVucyBkaWVzZSBaYWhsZW4gZWlubWFsIGdlbmF1ZXIgYW4ga29tbXQgZGllIEZyYWdlIGF1ZiBXb3JhbiBkaWVzZSBFeHRyZW1lbiBaYWhsZW4gaW4gZGVuIHZlcsO2ZmZlbnRsaWNodW5nZW4genVyw7xja3p1ZsO8aHJlbiBzaW5kPyBBbiBkaWVzZW0gUHVua3QgZGVyIEFuYWx5c2Uga8O2bm5lbiB3aXIgbnVyIFNwZWt1bGllcmVuIGRpZSBTcGl0emVuIGvDtm5udGVuIGFsbGVyZGluZ3MgYW4gZGVuIFZlcsO2ZmZlbnRsaWNodW5nZW4gZ3Jvw59lciwgZGVuIE1hcmt0IGJlc3RpbW1lbmRlbiBQbGF0dGZvcm1lbiB3aWUgZGVyIFBTMi8zLCBkZXIgWGJveCB1bmQgZGVuIFBsYXRmb3JtZW4gdm9uIE5pbnRlbmRvIHdpZSBHYW1lY3ViZSBvZGVyIFdpaSB6dXLDvGNrenVmw7xocmVuIHNlaW4uICANCkhpZXJ6dSBhYmVyIHNww6R0ZXIgW21laHJdKCNTYWxlc1BlclBsYXRmb3JtKS4NCg0KDQojIyMgR2FtZSBTYWxlcyB7I1ZpZGVvR2FtZVJlbGVhc2VzU2FsZXN9DQoNClVtIGRlbSB6d2VpdGVuIFRlaWwgZGVyIEZyYWdlc3RlbGx1bmcgYXVmIGRlbiBHcnVuZCBnZWhlbiB6dSBrw7ZubmVuIG3DvHNzZW4gd2lyIGVybmV1dCBkaWUgRGF0ZW4gZGVyIFRhYmVsbGUgdmdzYWxlcyBtaXRoaWxmZSBkZXIgRnVua3Rpb24gKmdyb3VwX2J5KFllYXIpKiBhbmhhbmQgZGVyIEphaHJlIFp1c2FtbWVuZmFzc2VuLiBOdW4gZXJoYWx0ZW4gd2lyIHdpZWRlciBkaWUgbmFjaCBkZW4gSmFocmVuIHp1c2FtbWVuZ2VmYXNzdGUgVGFiZWxsZSBkZXJlbiBFaW50csOkZ2Ugd2lyIG1pdCBkZXIgRnVua3Rpb24gICpkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSogenVzYW1tZW5mYXNzZW4uIERlbSBBdWZtZXJrc2FtZW4gTGVzZXIgd2lyZCBhdWZmYWxsZW4gZGFzIGhpZXIgZWluIGtsZWluZXIgYWJlciBmZWluZXIgVW50ZXJzY2hpZWQgenVtIHZvcmhlcmlnZW4gQXVmcnVmIGJlc3RlaHQuIFN0YXR0ICpBbnphaGwgPW4oKSogbnV0emVuIHdpciBoaWVyICpncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKSouIERpZXNlIEZ1bmt0aW9uIHN1bW1pZXJ0IGFsbGUgV2VydGUgZGVyIFNwYWx0ZSBHbG9iYWxfU2FsZXMgYXVmIHVuZCBzcGVpY2hlcnQgZGVuIGRlbiBXZXJ0IGluIGRpZSBTcGFsdGUgKmdyX3N1bSouIEF1ZmdydW5kIGRlciBmw7xyIGRpZXNlIGFuYWx5c2Ugd2VpdGVyaGluIEZlaGxlcmhhZnRlbiBEYXRlbiB2ZXJ3ZW5kZW4gd2lyIGVybmV1dCBkaWUgRnVua3Rpb24gKmZpbHRlcigpKiB1bSBhbGxlIGZlaGxlbmRlbiBKYWhyZXNlaW50csOkZ2Ugc293aWUgZGllIEphaHJlIDIwMjAgdW5kIDIwMTcgaGVyYXVzenVmaWx0ZXJuLiAgRGllc2UgRGF0ZW4gc3BlaWNoZXJuIHdpciB3aWVkZXIgYWxzICpkYXRhLmZyYW1lKiBpbiBkZXIgVmFyaWFibGUgKmdyb3VwZWQqIGFiLiBJbSBmb2xnZW5kZW4gdmVyd2VuZGVuIHdpciBlYmVuamVuZXMgZGF0YS5mcmFtZSB1bSBudXIgZGllIEVpbnRyw6RnZSBKYWhyIHVuZCAqZ3Jfc3VtKiB6dSBzZWxla3RpZXJlbiB1bmQgaW4gZGVyIFZhcmlhYmxlICpmaWx0ZXJlZCogYWJ6dXNwZWljaGVybi4gRGllIGVyaGFsdGVuZSBUYWJlbGxlIGhhdCBudW4gendlaSBTcGFsdGVuOiBKYWhyIHVuZCAqZ3Jfc3VtKi4gRGVzd2VpdGVyZW4gZXJzdGVsbGVuIHdpciBlcm5ldXQgZGllIFZhcmlhYmxlbiAqYXgqIHVuZCAqYXkqLiBOdW4gdmVyd2VuZGVuIHdpciAqcGxvdF9seSgpKiB1bSBtaXRoaWxmZSBkZXIgKnR5cGUgPSAnc2NhdHRlcicqIHVuZCAqbW9kZSA9ICdsaW5lcycqIFBhcmFtZXRlciBlaW4gTGluaWVuZGlhZ3JhbW0genUgZXJzdGVsbGVuLiBBdcOfZXJkZW0gbnV0emVuIHdpciBkaWUgKmxheW91dCgpKiBmdW5rdGlvbiB1bSBlaW5lbiB0aXRlbCB6dSBlcnN0ZWxsZW4sIHNvd2llIG1pdGhpbGZlIHVuc2VyZSBiZWlkZW4gVmFyaWFibGVuIGF4IHVuZCBheSBkaWUgQWNoc2VuIHp1IGJlc2NocmlmdGVuLg0KDQpgYGB7ciBwbG90KEdhbWVTYWxlc0J5WWVhciksIGluY2x1ZGU9VFJVRSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhcikgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICIgR2FtZSBTYWxlcyBwZXIgWWVhciAoaW4gbWlvKSINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGZpbGwgPSAndG96ZXJveScgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkdhbWUgU2FsZXMgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCkJldHJhY2h0ZW4gd2lyIG51biBkYXMgZW50c3RhbmRlbmUgRGlhZ3JhbW0gZsOkbGx0IHVucyB6dWVyc3QgYXVmLCBkYXNzIGVzIGRlbSB2b3JoZXJpZ2VuIHJlY2h0IMOkaG5saWNoIHNpZWh0LiBEaWVzIGlzdCBrYXVtIHZlcnd1bmRlcmxpY2ggdW5kIHN0ZWxsdCBrZWluZW4gbmVubmVuc3dlcnRlbiBXaXNzZW5zZ2V3aW5uIGRhLiBEZXIgd29obCBOZW5uZXN3ZXJ0ZXN0ZSB1bnRlcnNjaGllZCBpc3QgZGFzIEZlaGxlbiBkZXMgQW5zdGllZ3MsIHdlbGNoZXIgaW4gZGVyIEFuemFobCBkZXIgR2FtZXJlbGVhc2VzIHp1bSBKYWhyIDIwMTUgZmVzdHp1c3RlbGxlbiB3YXIuIER1cmNoIGRlbiBkaXJla3RlbiBWZXJnbGVpY2ggaXN0IGRpZXMgYWxsZXJkaW5ncyBlaW4gZ3V0ZXIgWmVpdHB1bmt0IHVtIHVucyBtaXQgdW5zZXJlciBad2VpdGVuIFRoZXNlIGF1c2VpbmFuZGVyenVzZXR6ZW4uICoiV2VyZGVuIGhldXR6dXRhZ2UgbWVociBTcGllbGUgUmVsZWFzdCB1bmQgVmVya2F1ZnQgYWxzIG5vY2ggMTk4MD8iKi4gRGllc2Ugc2VoZW4gd2lyIGF1ZmplZGVuZmFsbCBiZXN0w6R0aWd0IG9id29obCBGZXN0enVzdGVsbGVuIGlzdCwgZGFzcyBkaWUgYmVzdGVuIEphaHJlIHNvd29obCBpbiB2ZXJrw6R1ZmVuIGFscyBhdWNoIGluIGRlciBBbnphaGwgZGllIEphaHJlIDIwMDggdW5kIDIwMDkgd2FyZW4uIERpZXMgV2lyZnQgbmF0w7xybGljaCBkaWUgRnJhZ2UgYXVmIHdhcyBkZXIgR3J1bmQgZsO8ciBkaWVzZW4gVmVybGF1ZiBpc3QgdW5kIHfDpHJlIGVpbiBJbnRlcmVzc2FudGVyIGFuc2F0eiBmw7xyIGVpbmUgW3dlaXRlcmUgQXJiZWl0XSgjQXVzYmxpY2tJbkRpZVp1a3VuZnQpLg0KDQojIyMgU2FsZXMgcGVyIEdhbWUgDQoNCkRpZSBGcmFnZSBkaWUgV2lyIGFsbGVyZGluZ3MgYmVhbnR3b3J0ZW4ga8O2bm5lbiBpc3QgKiJXZXJkZW4gbmV1ZXJlIFNwaWVsZSBhdXRvbWF0aXNjaCBtZWhyIEdla2F1ZnQ/IiouIERhZsO8ciBrb21iaW5pZXJlbiB3aXIgZGllIGJlaWRlbiBiZXJlaXRzIFZlcndlbmRldGVuIGFuc8OkdHplLiANCldpciBmYXNzZW4gd2llZGVyIGRpZSBkYXRlbiBtaXRoaWxmZSB2b24gKmdyb3VwX2J5KFllYXIpKiBhbmhhbmQgZGVyIEphaHJlIFp1c2FtbWVuLiBEaWUgZXJoYWx0ZW5lIFRhYmVsbGUgZmFzc2VuIHdpciB3aWVkZXIgbWl0ICAqZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKSkqIHp1c2FtbWVuLiBEaWVzbWFsIG51dHplbiB3aXIgamVkb2NoIGVpbmUga29tYmluYXRpb24gYXVzICpzdW0oR2xvYmFsX1NhbGVzKSogdW5kICpuKCkqLiBXaXIgYWRkaWVyZW4gZGllIFNwYWx0ZSAqR2xvYmFsX1NhbGVzKiwgdGVpbGVuIGRpZXMgZHVyY2ggZGllIEFuemFobCBkZXIgRWludHLDpGdlIHVuZCBzcGVpY2hlcm4gZGVuIFdlcnQgaW4gZGllIFNwYWx0ZSAqZ2FtZXNhbGVzKiAoKmdhbWVzYWxlcyA9IHN1bShHbG9iYWxfU2FsZXMpL24oKSopLiBEYW5hY2ggZmlsdGVybiB3aXIgZGllIERhdGVuIGVybmV1dCB1bmQgc3BlaWNoZXJuIHNpZSBhbHMgKmRhdGEuZnJhbWUqIGluIGdyb3VwZWQgYWIuIERpZXNtYWwgc2VsZWt0aWVyZW4gd2llIGRpZSBFaW50csOkZ2UgZGVyIFNwYWx0ZSBKYWhyIHNvd2llICpnYW1lc2FsZXMqIHVuZCBzcGVpY2hlcm4gc2llIGluIGRlciBWYXJpYWJsZSAqZmlsdGVyZWQqIGFiLiBadWxldHp0IGVyc3RlbGxlbiB3aXIgZXJuZXV0IGRpZSBWYXJpYWJsZW4gKmF4KiB1bmQgKmF5KiB1bmQgdmVyd2VuZGVuICpwbG90X2x5KCkqIHVtIG1pdGhpbGZlIGRlciAqdHlwZSA9ICdzY2F0dGVyJyogdW5kICptb2RlID0gJ2xpbmVzJyogUGFyYW1ldGVyIGVpbiBMaW5pZW5kaWFncmFtbSB6dSBlcnN0ZWxsZW4gc293aWUgZGllICpsYXlvdXQoKSogZnVua3Rpb24gdW0gZWluZW4gdGl0ZWwgenUgZXJzdGVsbGVuIHVuZCBtaXRoaWxmZSB1bnNlcmUgYmVpZGVuIFZhcmlhYmxlbiBheCB1bmQgYXkgZGllIEFjaHNlbiB6dSBiZXNjaHJpZnRlbi4NCg0KYGBge3IgcGxvdChTYWxlc2J5R2FtZUJ5WWVhciksIGluY2x1ZGU9VFJVRSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhcikgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ2FtZXNhbGVzID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLGdhbWVzYWxlcykNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMgcGVyIEdhbWUiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5nYW1lc2FsZXMsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLCBmaWxsID0gJ3RvemVyb3knICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBwZXIgR2FtZSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANClNhaGVuIHNpY2ggZGllIGJlaWRlbiBEaWFncmFtbWUgZsO8ciBBbnphaGwgdW5kIFZlcmthdWZzemFobGVuIG5vY2ggcmVjaHQgw6RobmxpY2ggc3RlbGx0IHNpY2ggaGllciBlaW4gZGV1dGxpY2ggdW50ZXJzY2hpZWRsaWNoZXIgVmVybGF1ZiBkYS4gSXN0IGRlciBXZXJ0IHp3aXNjaGVuIDE5ODAgKDEuMjYpIHVuZCAxOTgzICgwLjk4KSBub2NoIHJlbGF0aXYgZ2VyaW5nIHN0ZWlndCBkaWVzZXIgTWFzc2l2IGbDvHIgZGllIEphaHJlIDE5ODQoMy41OSkgdW5kIDE5ODUoMy44NSkgYmV2b3IgZXIgMTk4NigxLjc2KSB1bmQgMTk4NygxLjM1KSB3aWVkZXIgYWJzaW5rdC4gR2VuYXVzbyBzY2huZWxsIHdpZSBkZXIgd2VydCBhYmdlc3Vua2VuIGlzdCBzdGVpZ3QgZXIgYWxsZXJkaW5ncyBhdWNoIHdpZWRlciBhdWYgMy4xNCgxOTg4KSBiZXZvciBlciAxOTg5IGRlbiBIw7ZjaHN0c3RhbmQgbWl0IDQuMzIgZXJyZWljaHQuIERhbmFjaCBzaW5rdCBkZXIgd2llZGVyIGFiIHVtIHNpY2ggbmFjaCBlaW5lbSBrdXJ6ZW4gYXVzc2NobGFnIDE5OTIgaW4gZGVuIEphaHJlbiBiaXMgMjAxNCBhdWYgZWluZW4gcmVsYXRpdiBzdGV0aWdlbiBXZXJ0IFp3aXNjaGVuIDAuNSB1bmQgMC43IGVpbnp1cGVuZGVsbiBlcnN0IDIwMTUgdW5kIDIwMTYgc2lua3QgZGllc2VyIHVudGVyIDAuNS4gRGllc2UgRXh0cmVtZW4gYXVzc2NobMOkZ2UgaW4gZGVuIEZyw7xoZXJlbiBKYWhyZW4gbGFzc2VuIHNpY2ggbWl0IGRlciBHZXJpbmdlbiBhbnphaGwgZGVyIFNwaWVsZSBlcmtsw6RyZW4uIEVpbnplbG5lIGd1dGUgbGF1ZmVuZGUgU3BpZWxlIG1hY2hlbiBoaWVyIG5vY2ggZWluZW4gR3Jvw590ZWlsIGRlcyBNYXJrdHMgYXVzIHdvaGluZ2VnZW4gc2ljaCBuZXVlcmUgc3BpZWxlLCBzb3dvaGwgZ2VnZW4gZWluZSBHcm/Dn3phaGwgdm9uIGJlcmVpdHMgZXRhYmxpZXJ0ZW4gU3BpZWxlIGFscyBhdWNoIGVpbmUgZ3Jvw59lIEFuemFobCBuZXVlciBSZWxlYXNlcywgZHVyY2hzZXR6ZW4gbcO8c3Nlbi4NCg0KIyMgey19DQoNCioqKg0KDQojIFBsYXRmb3JtIEFuYWx5c2UgeyNQbGF0Zm9ybWFuYWx5c2V9DQoNCmBgYHtyIG5vcGxvdCwgZWNobyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCBpbmNsdWRlID1GQUxTRSx9DQp2Z3NhbGVzICU+JSANCiAgcGxvdF9seSgNCiAgICB4PX5QbGF0Zm9ybSwNCiAgICBzdHJva2U9SSgiYmxhY2siKSwNCiAgICBuYW1lPSJBbW91bnQgYnkgUGxhdGZvcm0iKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlPSJBbW91bnQgYnkgUGxhdGZvcm0iKQ0KdmdzYWxlcyAlPiUgDQogIHBsb3RfbHkgJT4lIA0KICBhZGRfYm94cGxvdCgNCiAgICB4PX5QbGF0Zm9ybSwNCiAgICBzdHJva2U9SSgiYmxhY2siKSwNCiAgICBuYW1lPSJBbW91bnQgYnkgUGxhdGZvcm0iKSAlPiUgDQogIGxheW91dCgNCiAgICB0aXRsZT0iQW1vdW50IGJ5IFBsYXRmb3JtIikNCg0KdmdzYWxlcyAlPiUgDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKA0KICAgIHg9fkdsb2JhbF9TYWxlcywNCiAgICB5PX5QbGF0Zm9ybSwNCiAgICBuYW1lPSJTYWxlcyBieSBQbGF0Zm9ybSAoaW4gbWlvKSIpICU+JSANCiAgbGF5b3V0KA0KICAgIHRpdGxlPSJTYWxlcyBieSBQbGF0Zm9ybSAoaW4gbWlvKSIpDQoNCmBgYA0KDQpWaWVkZW9zcGllbGUgZ2lidCBlcyBpbiBkZW4gVW50ZXJzY2hpZWRsaWNoc3RlbiBGYXJiZW4gdW5kIEZvcm1lbi4gV2FzIFNpZSBqZWRvY2ggYWxsZSBnZW1laW5zYW0gaGFiZW4gaXN0LCBkYXNzIHNpZSBhdWYgZWluZW0gbWVkaXVtIEdlc3BpZWx0IHdlcmRlbi4gU2VpIGVzIFNvbnlzIFBsYXlzdGF0aW9uLCBNaWNyb3NvZnRzIHhCb3gsIE5pbnRlbmRvcyBTcGllbGVrb25zb2xlbiB3aWUgZGllIFdpaSBvZGVyIGRlciBlaW5mYWNoZSBkZXNrdG9wIFBDLiBEaWUgRnJhZ2UgZGllIFNpY2ggamVkZXIgRmFuIGplZG9jaCBzY2hvbm1hbCBnZXN0ZWxsdCBoYXQgdW5kIMO8YmVyIGRpZSBow6R1ZmlnIGRpc2t1dGllcnQgd2lyZCBpc3Qgd2VsY2hlIGlzdCBkaWUgQmVzdGU/IERhIGRpZXMgaW1tZXIgaW0gQXVnZSBkZXMgQmV0cmFjaHRlcnMgbGllZ3QgdmVyc3VjaGVuIHdpciB6dW1pbmRlc3RlbnMgenUga2zDpHJlbiAqV2VsY2hlIFBsYXRmb3JtIGlzdCBkaWUgYmVzdGUgaW4gQW56YWhsIHZlcmvDpHVmZW4/IFdlbGNoZSBpbiBBbnphaGwgZGVyIEdhbWUgUmVsZWFzZXM/Ki4gWnVtIGJlYW50d29ydGVuIGRpZXNlciBGcmFnZSBpc3QgZGVyIFZvcmhhbmRlbmUgRGF0ZW5zYXR6IG5pY2h0IGdhbnogb3B0aW1hbCBhYmVyIGhpZXJ6dSB3ZWl0ZXJlcyBpbSBbRmF6aXRdKCNBdWZnZXRyZXRlbmVQcm9ibGVtZSkuDQoNCg0KIyMgUGxhdGZvcm0gUmFua2luZyBHbG9iYWwgey50YWJzZXR9DQoNCiMjIyBBbW91bnQNCg0KVW0gc2ljaCBlaW5lbiBndXRlbiDDnGJlcmJsaWNrIMO8YmVyIGRpZSBSYW5raW5ncyBkZXIgUGxhdGZvcm1lbiB6dSB2ZXJzY2hhZmZlbiBudXR6ZW4gd2lyIGhpZXIgZWluIFBhcmV0b2RpYWdyYW1tLiBEaWVzIHNpbmQgbmFjaCBkZXIgR3LDtsOfZSBkZXIgV2VydGUgc29ydGllcnRlIFPDpHVsZW5kaWFncmFtbWUuIFp1bSBlcnN0ZWxsZW4gZGVzIERpYWdyYW1tcyBicmF1Y2hlbiB3aXIgenVlcnN0IGVpbm1hbCB3aWVkZXIgdW5zZXJlbiBEYXRlbnNhdHogZGVuIHdpciBkaWVzbWFsIG1pdGhpbGZlIGRlcyAqZ3JvdXBfYnkqIEJlZmVobHMgYW5oYW5kIGRlciAqUGxhdGZvcm0qIGdydXBwaWVyZW4uIERhbmFjaCBudXR6ZW4gd2lyIGVybmV1dCAqc3VtbWFyaXplKEFuemFobCA9bigpKiB1bSBkaWUgRWludHLDpGdlIGFienV6w6RobGVuIHVuZCBkZW4gd2VydCBhbHMgQW56YWhsIGFienVzcGVpY2hlcm4uIFVtIGRpZSBFaW50csOkZ2UgZGVyIEFuemFobCBuYWNoIHp1IHNvcnRpZXJlbiBudXR6ZW4gd2lyIHp1ZXJzdCBkZW4gQmVmZWhsICpncm91cGVkW29yZGVyKGdyb3VwZWRcJEFuemFobCksZGVjcmVhc2luZyA9IEZBTFNFXSogdW5kIHdlaXNlbiBkYXMgRXJnZWJuaXMgZGVyIG5ldWVuIFRhYmVsbGUgKk9yZGVyZWQqIHp1LiBEaWVzZXIgQmVmZWhsIHNpZWh0IHJlbGF0aXYga29tcGxleCBhdXMgbMOkc3N0IHNpY2ggamVkb2NoIHJlY2h0IGVpbmZhY2ggYXVmZHLDtnNlbG4uIE9yZGVyIHNvcnRpZXJ0IGRpZSBUYWJlbGxlIG5hY2ggZGVyIGdlZ2ViZW5lbiBTcGFsdGUgdW5kIGRlciBQYXJhbWV0ZXIgKmRlY3JlYXNpbmcgPSogZ2lidCBhbiBvYiBkZXIgZ3LDtsOfdGUgV2VydCBhbSBBbmZhbmcgb2RlciBFbmRlIHN0ZWhlbiBzb2xsLiBEYXMgRG9sbGFyIFplaWNoZW4gc2VsZWt0aWVydCBoaWVyYmVpIGRpZSBTcGFsdGUgbWl0IGRlbSBkYWhpbnRlcnN0ZWhlbmRlbiBOYW1lIGF1cyBkZXIgdm9yaGVyIHN0ZWhlbmRlbiBUYWJlbGxlIGdldHJldSBuYWNoIGRlbSBTY2hlbWEgKlRhYmVsbGVcJFNwYWx0ZSouIERhbmFjaCBtw7xzc2VuIHdpciBub2NoIGRpZSBTcGFsdGUgKlBsYXRmb3JtKiBhbHMgZmFrdG9yIGVpbmxlc2VuIHdlbGNoZXMgd2lyIG1pdCBkZW0gQmVmZWhsICphc19mYWN0b3Iob3JkZXJlZFwkUGxhdGZvcm0pKiB0dW4uIERhbmFjaCBlcnN0ZWxsZW4gd2lyIHVuc2VyZSBiZWlkZW4gVmFyaWFibGVuIGF4IHVuZCBheSB6dXIgQWNoc2VuYmVzY2hyaWZ0dW5nLiBOdW4ga29tbWVuIHdpciB6dXIgZWlnZW50bGljaGVuIERpYWdyYW1tZXJzdGVsbHVuZy4gV2lyIGdlYmVuIGRpZSBUYWJlbGxlICpvcmRlcmVkKiB3ZWl0ZXIgYW4gKnBsb3RfbHkoKSogdW5kIG51dHplbiAqYWRkX2JhcnMqIHVtIGVpbiBCYWxrZW5kaWFncmFtbSB6dSBlcnN0ZWxsZW4uIERlciB1bnRlcnNjaGllZCB6d2lzY2hlbiBCYWxrZW4gdW5kIFBhcmV0b2RpYWdyYW1tIGxpZWd0IGhpZXJiZWkgaW4gZGVyIFBhcmFtZXRlcsO8YmVyZ2FiZS4gU2NoYXVlbiB3aXIgdW5zIGRpZSByZWxldmFudGVuIFRlaWxlIGVpbm1hbCBnZW5hdWVyIGFuLiBEZXIgaW50ZXJlc3NhbnRlIFRlaWwgcGFzc2llcnQgaGllcmJlaSBiZWkgZGVyIHp1d2Vpc3VuZyBkZXIgWC1BY2hzZSB1bmQgaGllciBzZWhlbiB3aXIgYXVjaCBkZW4gR3J1bmQgZsO8ciB1bnNlcmUgdm9yaGVyaWdlIHVtd2FuZGx1bmcgZGVyIFNwYWx0ZSBQbGF0Zm9ybSB6dSBlaW5lbSBmYWt0b3IuICp4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxBbnphaGwsIC5kZXNjPSJ0cnVlIikseT1+QW56YWhsKiBXaXIgbnV0emVuIGRlbiBCZWZlaGVsICpmY3RfcmVvcmRlcigpKiB1bSBkaWUgUGxhdGZvcm1lbiBuYWNoIGRlciBBbnphaGwgc29ydGllcnQgaGVyIGFuenVvcmRuZW4uIERlciBlcnN0ZSBQYXJhbWV0ZXIgaXN0IGhpZXJiZWkgZGllIHp1IHNvcnRpZXJlbmRlIFNwYWx0ZSwgZGVyIHp3ZWl0ZSBkaWUgbmFjaCBkZXIgc29ydGllcnQgd2VyZGVuIHNvbGwuIERlciBQYXJhbWV0ZXIgLmRlc2Mgc3RlaHQgZGVzY2VuZGluZyB1bmQgYmVzdGltbXQgd2llIHNvcnRpZXJ0IHdlcmRlbiBzb2xsLCBpbiB1bnNlcmVtIGZhbGwgZGVyIGdyw7bDn3RlIFdlcnQgenVlcnN0LiBadSBndXRlciBsZXR6dCBnZWJlbiB3aXIgZGVtIERpYWdyYW1tIG5vY2ggZWluZW4gTmFtZW4sIHdlaXNlbiBkaWUgRmFyYnBhbGV0dGUgenUgdW5kIHNldHplbiBkYXMgTGF5b3V0IG1pdCBkZW0gVGl0ZWwgc293aWUgdW5zZXJlbiBiZWlkZW4gQWNoc2VuYmVzY2hyaWZ0dW5nZW4uDQoNCmBgYHtyIHBsb3QsIGVjaG8gPSBUUlVFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nbWFya3VwJyx9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKSANCg0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkQW56YWhsKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KKQ0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxBbnphaGwsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkFuemFobCwNCiAgICAgICAgICAgbmFtZT0iR2FtZSBBbW91bnQgYnkgUGxhdGZvcm0iICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJHYW1lIEFtb3VudCBieSBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgDQogICAgICAgICApDQpgYGANCg0KQmVpbSBCZXRyYWNodGVuIGRlcyBEaWFncmFtbXMgZXJrZW5uZW4gd2lyIGRhcyB3ZWRlciBnYW56IGFsdGUgbm9jaCBnYW56IG5ldWUgUGxhdGZvcm1lbiBkaWUgTmFzZSB2b3JuZSBoYWJlbi4gQW4gZGVuIGVyc3RlbiBiZWlkZW4gU3RlbGxlbiB1bmQgd2VpdCBhYmdlc2NobGFnZW4gdm9tIFJlc3QgZGVyIFBsYXRmb3JtZW4gZmluZGVuIHNpY2ggaGllciBkZXIgRFMgdm9uIE5pbnRlbmRvICgyMTYzKSB1bmQgZGllIFBsYXlzdGF0aW9uIDIgdm9uIFNvbnkgKDIxNjEpLiBEaWVzIGlzdCB3ZWl0ZXIgbmljaHQgVmVyd3VuZGVybGljaCBkYSBiZWlkZSBhdWNoIGRpZSBLb25zb2xlbiBzaW5kIGRpZSBzaWNoIFtXZWx0d2VpdCBhbSBiZXN0ZW4gdmVya2F1ZnQgaGFiZW5dKGh0dHBzOi8vZGUuc3RhdGlzdGEuY29tL3N0YXRpc3Rpay9kYXRlbi9zdHVkaWUvMTYwNTQ5L3VtZnJhZ2UvYW56YWhsLWRlci13ZWx0d2VpdC12ZXJrYXVmdGVuLXNwaWVsa29uc29sZW4tbmFjaC1rb25zb2xlbnR5cGVuLykuIEVpbiB3ZWl0ZXJlciBHcnVuZCBmw7xyIGRlcmVuIGhvaGUgU3BpZWxlYW56YWhsIGlzdCB2ZXJtdXRsaWNoIGF1Y2ggZGVyZW4gU3RlbGx1bmcgYWxzIFBsYXR6aGlyc2NoZSBpbSBLb25zb2xlbi0gYnp3LiBIYW5kaGVsZG1hcmt0LiBXZWl0ZXJoaW4ga8O2bm5lbiB3aXIgZXJrZW5uZW4gZGFzIGVzIG1laXN0IGRpZSDDpGx0ZXJlIEdlbmVyYXRpb25lbiBlaW5lciBLb25zb2xlIHNpbmQgZGllIG1laHIgU3BpZWxlIGhhYmVuLiBEaWUgUGxheXNhdGF0aW9uIDIgaGF0IGJlaXNwaWVsc3dlaXNlIG1laHIgU3BpZWxlIGFscyBQUzMgdW5kIFBTNCwgZGllIFhib1gzNjAgbWVociBhbHMgZGllIHhCb3hPbmUgdW5kIGRlciBEUyBtZWhyIGFscyBkZXIgM0RTLiBEaWVzIHNjaGVpbnQgamVkb2NoIG5pY2h0IGF1ZiBkaWUgZXJzdGUgR2VuZXJhdGlvbiB6dXp1dHJlZmZlbi4gRGllIFBsYXlzdGF0aW9uIGhhdCBtZWhyIHZlcmvDpHVmZSBhbHMgZGllIFBTNCBhYmVyIHdlbmlnZXIgYWxzIFBTMyB1bmQgUFMyLiBEaWUgWGJveCBtZWhyIGFscyBkaWUgWGJveE9uZSBhYmVyIHdlbmlnZXIgYWxzIGRpZSBYYm94MzYwLg0KDQoNCiMjIyBTYWxlcw0KDQpTY2hhdWVuIHdpciB1bnMgbnVuIGRpZSBWZXJrYXVmc3phaGxlbiBkZXIgU3BpZWxlIGRlciBlaW56ZWxuZW4gUGxhdGZvcm1lbiBhbi4gV2lyIHZlcndlbmRlbiBoaWVyIHdpZWRlciBlaW4gUGFyZXRvZGlhZ3JhbW0gdW5kIGdlaGVuIMOkaG5saWNoIGRlcyB2b3JoZXJpZ2VuIERpYWdyYW1tcyB2b3IuIFp1ZXJzdCBudXR6ZW4gd2lyIHdpZWRlciBkaWUgKmdyb3VwX2J5KiBGdW5rdGlvbiB1bSBuYWNoIGRlbiBQbGF0Zm9ybWVuIHp1IGdydXBwaWVyZW4uIERhIHdpciBudW4gYWJlciBkaWUgVmVya2F1ZnN6YWhsZW4gYmV0cmFjaHRlbiB3b2xsZW4gbnV0emVuIHdpciAqc3VtbWFyaXplKCkqIGF1ZiBkaWUgKkdsb2JhbF9TYWxlcyogU3BhbHRlLiBOdW4gbnV0emVuIHdpciBkaWUgKnJlbmFtZSgpKiBmdW5rdGlvbiB1bSBkaWUgc28gZW50c3RhbmRlbmUgU3BhbGUgKnN1bShHbG9iYWxfU2FsZXMpKiBpbiAqR2xvYmFsX1NhbGVzKiB1bXp1YmVuZW5uZW4uIERpZXMgaGF0IGtlaW5lbiB3ZWl0ZXJlbiBOdXR6ZW4gYXXDn2VyIHVucyBpbSBzcMOkdGVyZW4gVmVybGF1ZiBkaWUgUmVmZXJlbnppZXJ1bmcgZGVyIFNwYWx0ZSBlaW5mYWNoZXIgenUgbWFjaGVuLiBVbSBzcMOkdGVyIG5hY2ggZGllc2VyIG5ldSBlcnN0ZWxsdGVuIFNwYWx0ZSBzb3J0aWVyZW4genUga8O2bm5lbiBtw7xzc2VuIHdpciBkaWVzZSB6dWVyc3QgaW4gZWluZW4gVmVjdG9yIHVtd2FuZGVsbi4gRGllcyB0dW4gd2lyIG1pdCBkZW0gQmVmZWhsICpncm91cGVkXCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkXCRHbG9iYWxfU2FsZXMpKi4gTnVuIGvDtm5uZW4gd2lyIGRpZSBUYWJlbGxlIHNvcnRpZXJlbiB1bmQgaW4gZGVyIFZhcmlhYmxlIG9yZGVyZWQgYWJzcGVpY2hlcm4gDQoqb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWRcJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0qLiBBbHMgbGV0enRlbiBTY2hyaXR0IGJldm9yIGVzIGFuIGRpZSBlcnN0ZWxsdW5nIGRlcyBEaWFncmFtbXMgZ2VodCB3YW5kZWxuIHdpciBub2NoIGRpZSBTcGFsdGUgUGxhdGZvcm0gaW4gZWluZW4gRmFjdG9yIHVtICpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkXCRQbGF0Zm9ybSkqIHVuZCBlcnN0ZWxsZW4gZXJuZXV0IHVuc2VyZSBBY2hzZW5iZXNjaHJpZnR1bmdlbiBheCB1bmQgYXkuIFp1ciBlcnN0ZWxsdW5nIGRlcyBEaWFncmFtbXMgw7xiZXJnZWJlbiB3aXIgdW5zZXJlICpvcmRlcmVkKiBUYWJlbGxlIGFuIGRpZSAqcGxvdF9seSgpKiBmdW5rdGlvbiB1bmQgbnV0emVuICphZGRfYmFycyogdW0gZWluIEJhbGtlbmRpYWdyYW1tIHp1IGVyc3RlbGxlbi4gSGllciB2ZXJ3ZW5kZW4gd2lyIHdpZWRlciBkaWUgUGFyYW1ldGVyICp4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksIHk9fkdsb2JhbF9TYWxlcyogdW0gZGVuIHggd2VydCwgYWxzbyBkaWUgUGxhdGZvcm1lbiBuYWNoIGRlbiBHbG9iYWwgU2FsZXMgenUgc29ydGllcmVuIGJldm9yIHdpciBkZW4gbmFtZW4gdW5kIGRpZSBGYXJiZSBkZXMgRGlhZ3JhbW1zIHNldHplbi4gWnUgZ3V0ZXIgTGV0enQgYmVudXR6ZW4gd2lyIG5vY2ggZGllIExheW91dCBmdW5rdGlvbiB1bSBkZW0gRGlhZ3JhbW0gZWluZW4gVGl0ZWwgenUgZ2ViZW4gdW5kIHVuc2VyZSBiZWlkZW4gQWNoc2VuYmVzY2hyaWZ0dW5nZW4genUgZXJzdGVsbGVuLg0KDQpgYGB7ciBwbG90KFBsYXRmb3JtUmFua2luZ19HbG9iYWwpLCBlY2hvID0gVFJVRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J21hcmt1cCcsfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFBsYXRmb3JtKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2xvYmFsIFNhbGVzIChpbiBtaW8pIg0KDQopDQoNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgQW1vdW50IGJ5IFBsYXRmb3JtIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgQW1vdW50IGJ5IFBsYXRmb3JtIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANClNjaGF1ZW4gd2lyIHVucyBkYXMgRW50c3RhbmRlbmUgRGlhZ3JhbW0gZWlubWFsIGF1ZiBmYWxsZW4gdW5zIGRpcmVrdCB6d2VpIERpbmdlIGF1Zi4gWnVtIGVpbmVuIGZlaGx0IGRlciBOaW50ZW5kbyBEUyBhdWYgZGVtIFNwaXR6ZW5wbGF0eiB6dXNhbW1lbiBtaXQgZGVyIFBTMiB1bmQgaXN0IG51ciBhdWYgUGxhdHogNSwgenVtIGFuZGVyZW4gaXN0IGRlciBVbnRlcnNjaGllZCB6d2lzY2hlbiBkZW4gU3BpdHplbnBsw6R0emVuIGJ6dyBkZW0gU3BpdHplbnBsYXR6IHVuZCBkZW0gcmVzdCBkZXIgdG9wIDUgZGV1dGxpY2ggZ2VyaW5nZXIuIFdhcmVuIGVzIGJlaSBkZXIgU3BpZWxlYW56YWhsIG5vY2ggZmFzdCA0MCUgdW50ZXJzY2hpZWQgendpc2NoZW4gcGxhdHogMS8yIHVuZCBwbGF0eiAzLTQgc28gc2luZCBlcyBoaWVyIG51ciBrbmFwcCAyMCUuIERpZSBSZXN0bGljaGVuIHBsw6R0emUgZGVyIFRvcCA1IHNpbmQgYWxsZXJkaW5ncyBncsO2w590ZW50ZWlscyBnbGVpY2ggZ2VibGllYmVuLiBadXPDpHR6bGljaCB6dW0gYWJzYWNrZW4gZGVzIE5pbnRlbmRvIERTIHZvbiBwbGF0eiAxIGF1ZiBwbGF0eiA1IGhhdCBudXIgZGllIFhib1gzNjAgaWhyZSBQb3NpdGlvbiBpbiBkZXIgUmFuZ2xpc3RlIHZlcsOkbmRlcnQuDQoNCiMjIHstfQ0KDQojIyMjIyAqSGFiZW4gw4RsdGVyZSBQbGF0Zm9ybWVuIEF1dG9tYXRpc2NoIG1laHIgU3BpZWxlIHVuZCBWZXJrw6R1ZmU/KiB7I1BsYXRmb3JtUmFua2luZ0dsb2JhbF9FbmR9DQoNCkJlaW0gQmV0cmFjaHRlbiBiZWlkZXIgRGlhZ3JhbW1lIG9kZXIgc29nYXIgbnVyIGVpbmVtIGRlciBEaWFncmFtbWUgZXJrZW5udCBkZXIgQXVmbWVya3NhbWUgQmV0cmFjaHRlciByZWxhdGl2IHNjaG5lbGwgZGFzIGhpZXIga2VpbmUgUGF1c2NoYWxhbnR3b3J0IGF1ZiBkaWVzZSBGcmFnZXN0ZWxsdW5nIG3DtmdsaWNoIGlzdC4gRGllcyBpc3QgYWJlciBpcmdlbmR3aWUgenUgZXJ3YXJ0ZW4gZ2V3ZXNlbiBlcyBnaWJ0IHNvIHZpZWxlIEZha3RvcmVuIGRpZSBkZW4gRXJmb2xnIGVpbmVyIGJlc3RpbW10ZW4gUGxhdGZvcm0gYmVzdGltbWVuIHVuZCBlcyBpc3QgdW5tw7ZnbGljaCBkaWVzZXMgYW4gZWluZW0gRmFrdG9yIGZlc3R6dWxlZ2VuLiBXd2VsY2hlIEZyYWdlIHdpciBhbGxlcmRpbmdzIGJlYW50d29ydGVuIGtvbm50ZW4sIHp1bWluZGVzdGVucyB0ZWlsd2Vpc2UsIGlzdCBkaWUgRnJhZ2UgbmFjaCBkZXIgImJlc3RlbiBQbGF0Zm9ybS4gRGllICoqUFMyKiogaXN0IHNvd29obCB3ZWl0IG9iZW4gaW4gZGVyIFNwaWVsZWFuemFobCwgYWxzIGF1Y2ggU3BpdHplbnJlaXRlciBpbiBkZW4gR2FtdmVya8OkdWZlbi4gRGVyIE5pbnRlbmRvIERTIGlzdCB6d2FyIGluIGRlciBTcGllbGVhbnphaGwgc29nYXIga25hcHAgdm9yIGRlciBQUzIgaW4gZGVuIHZlcmvDpHVmZW4gYWJlciB3ZWl0IGFiZ2VzY2hsYWdlbiBhdWYgUGxhdHogNS4gQXVzc2NobGFnZ2ViZW5kZXIgYWxzIHZlcmdsZWljaHNhcmd1bWVudCB3w6RyZSBqZWRvY2ggZGllIEFuemFobCBkZXIgVmVya2F1ZnRlbiBTcGllbGUgcHJvIFNwaWVsIGRvY2ggd2VpdGVyZXMgaGllcnp1IGltIFtBdXNibGljayBpbiBkaWUgWnVrdW5mdF0oI0F1c2JsaWNrSW5EaWVadWt1bmZ0KQ0KDQpPZmZlbnNpY2h0bGljaCBpc3QgZWluIERhdGVuc2F0eiB6dSBBbnphaGwgZGVyIFNwaWVsZXZlcmvDpHVmZSB2b3JhbGxlbSBlaW4gc28gbMO8Y2tlbmhhZnRlciBuaWNodCBvcHRpbWFsIGFiZXIgZGF6dSB3ZWl0ZXJlcyBpbSBbRmF6aXRdKCNBdWZnZXRyZXRlbmVQcm9ibGVtZSkuDQoNCioqKg0KDQojIFBsYXRmb3JtIFNhbGVzIG5hY2ggUmVnaW9uIHsjUGxhdGZvcm1SYW5raW5nQnlSZWdpb259DQoNCkRhIHdpciBudW4gZ2VrbMOkcnQgaGFiZW4gd2VsY2hlIFBsYXRmb3JtZW4gZGllIE5hc2Ugdm9ybmUgaGFiZW4gd8OkcmUgZXMgZG9jaCBJbnRlcmVzc2FudCBoZXJhdXN6dWZpbmRlbiBvYiBlcyBSZWdpb25hbGUgdW50ZXJzY2hpZWRlIGdpYnQuDQoqRmF2b3Jpc2llcmVuIHZlcnNjaGllZGVuZSBSZWdpb25lbiB2ZXJzY2hpZWRlbmUgUGxhdGZvcm1lbj8gVmVya2F1ZmVuIGRpZSBSZWdpb25lbmhlaW1pc2NoZW4gUGxhdGZvcm1lbiBhdXRvbWF0aXNjaCBhdWNoIGRpZSBtZWlzdGVuIFNwaWVsZT8qDQoNCkhpZXJiZWkga8O2bm5lbiB3aXIgbmF0w7xybGljaCBudXIgZGllIFZlcmthdWZzemFobGVuIGhlcmFuemllaGVuLiBUaGVvcmV0aXNjaCB3w6RyZSBhdWNoIGVpbiBWZXJnbGVpY2ggaW4gYW56YWhsIGRlciBTcGllbGUgbcO2Z2xpY2ggd8O8cmRlIGFiZXIgZGllc2UgQXJiZWl0IFNwcmVuZ2VuIGRhIGRlciBEYXRlbnNhdHogZGllc2UgSW5mb3JtYXRpb25lbiBuaWNodCBvaG5lIHdlaXRlcmVzIFtoZXJnaWJ0XSgjQXVmZ2V0cmV0ZW5lUHJvYmxlbWUpLg0KWnVtIEJlYW50d29ydGVuIGRpZXNlciBGcmFnZSBiZW51dHplbiB3aXIgZXJuZXV0IFBhcmV0b2RpYWdyYW1tZSB1bmQgdW0gc2ljaCBlaW5lbiBHcm9iZW4gw7xiZXJibGljayB6dSBzY2hhZmZlbiBLcmVpc2RpYWdyYW1tZS4gRGllc2UgaGFiZW4gaWhyZSBlaWdlbmVuIFtQcm9ibGVtZV0oI0F1ZmdldHJldGVuZVByb2JsZW1lKSBiaWV0ZW4gdW5zIGFiZXIgZWluIGd1dGVzIFRvb2wgenVyIGdyb2JlbiDDvGJlcnNpY2h0IMO8YmVyIGRpZSBQcm96ZW50dWFsdmVydGVpbHVuZyBkZXIgS29uc29sZW4gdW5kIGJyaW5ndCBldHdhcyBBYndlY2hzbHVuZyBpbiBkaWVzZSBiaXNoZXIgc2VociBCYWxrZW5kaWFncmFtbSBsYXN0aWdlIGF1c2FyYmVpdHVuZy4NCg0KW0Vpbnp1d2VuZGVuIGhpZXJiZWkgaXN0XSgjQXVmZ2V0cmV0ZW5lUHJvYmxlbWUpLCBkYXNzIGRpZSBSZWdpb25lbiBuYXTDvHJsaWNoIHVudGVyc2NoaWVkbGljaCB2aWVsZSBFaW53b2huZXIgaGFiZW4uRWluIHZlcmdsZWljaCBkZXIgYWJzb2x1dGVuIFNhbGVzd2VydGUgaXN0IGhpZXJiZWkgbmF0w7xybGljaCBudXIgd2VuaWcgYXVzc2NobGFnZ2ViZW5kIHplaWd0IGFiZXIgZWluZW4gZ2VuZXJlbGxlbiBiZWxpZWJ0aGVpdHN0cmVuZCBkZXIgS29uc29sZW4gaW4gZGVuIGVpbnplbG5lbiBSZWdpb25lbiBhdWYuDQoNCiMjIFBsYXRmb3JtIFJhbmtpbmcgey50YWJzZXR9DQoNCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQojIyMjIEV1cm9wYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfRVUxKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEVVX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oRVVfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUGxhdGZvcm0sR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IkVVIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkVVIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQojIyMjIE5vcmQtQW1lcmlrYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfTkExKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJOQSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUGxhdGZvcm0sR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9Ik5BIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9Ik5BIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyMgSmFwYW4NCmBgYHtyIHBsb3QoUGxhdGZvcm1SYW5raW5nX0pQMSksIGVjaG8gPSBUUlVFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nbWFya3VwJyx9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSANCiAgc3VtbWFyaXplKHN1bShKUF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEpQX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiSlAgU2FsZXMgKGluIG1pbykiDQoNCikNCg0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFBsYXRmb3JtLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJKUCBTYWxlcyBBbW91bnQgYnkgUGxhdGZvcm0iICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJKUCBTYWxlcyBBbW91bnQgYnkgUGxhdGZvcm0iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KIyMjIGtyZWlzZGlhZ3JhbW1lIHsudGFic2V0fQ0KDQojIyMjIEV1cm9wYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfRVUyKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEVVX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oRVVfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+UGxhdGZvcm0sdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLA0KICAgICAgICAgICBuYW1lPSJFVSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iRVUgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQojIyMjIE5vcmQtQW1lcmlrYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfTkEyKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJOQSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5QbGF0Zm9ybSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsDQogICAgICAgICAgIG5hbWU9Ik5BIFNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJOQSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIyBKYXBhbg0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfSlAyKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEpQX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oSlBfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJKUCBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5QbGF0Zm9ybSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsDQogICAgICAgICAgIG5hbWU9IkpQIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkpQIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCg0KIyMgey19DQoNCg0KSW0gZ2VuZW5zYXR6IHp1ciBFVSwgaW4gZGVyIGRhcyBqYXBhbmlzY2hlIHVudGVybmVobWVuIFNvbnkgbWl0IGRlciBQUzIgdW5kIFBTMyBkaWUgbGlzdGUgYW5mw7xocnQsIGhhdCBpbiBkZW4gVVNBIGRhcyBMYW5kZXNlaWdlbmUgc29mdHdhcmV1bnRlcm5laG1lbiBNaWNyb3NvZnQgbWl0IGRlciBYYm94MzYwIGRpZSBOYXNlIHZvcm4uIEluIEphcGFuIGhpbmdlZ2VuIGlzdCB3aWUgenUgZXJ3YXJ0ZW4gZGVyIGphcGFuaXNjaGUgaGVyc3RlbGxlciBOaW50ZW5kbyBtaXQgZGVtIERTIGRlciBNYXJrZsO8aHJlci4NCg0KKioqDQoNCiMgUGxhdGZvcm0gU2FsZXMgaW0gbGF1ZmUgZGVyIEphaHJlIHsjU2FsZXNQZXJQbGF0Zm9ybX0NClVtIHNpY2ggZGFzIEdhbnplIGV0d2FzIGdlbmF1ZXIgYW56dXNjaGF1ZW4gYmV0cmFjaHRlbiB3aXIgZGllIEFuemFobCBkZXIgU2FsZXMgcGVyIFBsYXRmb3JtIGltIFZlcmxhdWYgZGVyIEphaHJlLg0KDQpVbSBlaW5lIMO8YmVybGFkdW5nIGRlcyBEaWFncmFtbXMgenUgdmVyaGluZGVybiB3ZXJkZW4gaGllciBhbGxlcmRpbmdzIG51ciBQbGF0dGZvcm1lbiBtaXQgbWluZGVzdGVucyA2MCBtaW8gaW4gU2FsZXMgaW0gZW50c3ByZWNoZW5kZW4gSmFociBiZXLDvGNrc2ljaHRpZ3QuIERpZXMgaGF0IGRlbiBOYWNodGVpbCBkYXMgZWluaWdlIHouVCB3aWNodGlnZSBEYXRlbiBGZWhsZW4sIGVpbiBXZWdsYXNzZW4gZWJlbmplbmVzIEZpbHRlcnMgZsO8cnQgYWJlciB6dSBrb21wbGV0dGVyIFVuw7xiZXJzaWNodGxpY2hrZWl0Lg0KYGBge3IgcGxvdChTYWxlc1BlclBsYXRmb3JtYnlZZWFyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgUGxhdGZvcm0pICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgICU+JSBmaWx0ZXIoZ3Jfc3VtPjYwKSU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCmdyb3VwZWQgPC0gZ3JvdXBlZCAlPiVhcnJhbmdlKGRlc2MoZ3Jfc3VtKSkgJT4lIA0KICBncm91cF9ieShZZWFyLCBQbGF0Zm9ybSkgJT4lDQogIHNsaWNlKDE6MykNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsUGxhdGZvcm0sZ3Jfc3VtKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMgcGVyIFBsYXRmb3JtIChpbiBtaW8pIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxjb2xvciA9IH5QbGF0Zm9ybSAsY29sb3JzID0gbXlQYWxldHRlKSU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBwZXIgUGxhdGZvcm0gZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQpIaWVyIGVya2VubmVuIHdpciBkYXMgUGxhdGZvcm0sIHdpZSB6dSBlcndhcnRlbiwgbWVpc3Qga3VyeiBuYWNoIFJlbGVhc2UgZGllIGdyw7bDn3RlbiBWZXJrYXVmc3phaGxlbiB2ZXJ6ZWljaG5lbi4NCg0KDQoqKioNCg0KIyBQdWJsaXNoZXIgVmVyZ2xlaWNoIHsjUHVibGlzaGVyUmVsZWFzZXN9DQoNCk51biBzdGVsbHQgc2ljaCBkaWUgRnJhZ2Ugb2Igc2ljaCBuZWJlbiBiZXN0aW1tdGVuIFBsYXRmb3JtZW4gYXVjaCBiZXN0aW1tdGUgRW50d2lja2xlci9QdWJsaXNoZXIgaMOkdWZlbi4gSGllcmJlaSBnZWhlbiB3aXIgZGF2b24gYXVzIGRhcyB2ZXJtdXRsaWNoIE5pbnRlbmRvIHVuZCBFQSBkaWUgTGlzdGUgYW5mw7xocmVuLg0KSGllcnp1IHZlcndlbmRlbiB3aXIgd2llZGVydW0gc29ydGVkIEJhci1DaGFydHMgdW5kIGvDvHJ6ZW4gZGllIE5hbWVuIHVtIGRpZSBCZWdyaWZmZSAiRW50ZXJ0YWlubWVudCIsICJJbnRlcmFjdGl2ZSIsICJHYW1lIiwgIkdhbWVzIiB1bmQgIlN0dWRpb3MiIGRhIGRpZXMgZGllIE5hbWVuIG51ciB1bm7DtnRpZyB2ZXJsw6RuZ2VydCB1bmQgRmlsdGVybiBQdWJsaXNoZXIgbWl0IEdlcmluZ2VuIEFuemFobCBhbiBHYW1lIFJlbGVhc2VzLg0KDQojIyBQdWJsaXNoZXIgey50YWJzZXR9DQoNCiMjIyBBbW91bnQNCmBgYHtyIHBsb3QyLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSAgDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUgZmlsdGVyKFB1Ymxpc2hlciE9IlVua25vd24iKQ0KDQoNCg0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRBbnphaGwpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCikNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUHVibGlzaGVyLEFuemFobCwgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+QW56YWhsLA0KICAgICAgICAgICBuYW1lPSJHYW1lIEFtb3VudCBieSBQdWJsaXNoZXIiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJHYW1lIEFtb3VudCBieSBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgIA0KICAgICAgICAgKQ0KYGBgDQojIyMgU2FsZXMNCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19HbG9iYWwpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KICBmaWx0ZXIoQW56YWhsPjEwMCkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJHbG9iYWwgU2FsZXMgKGluIG1pbykiDQoNCikNCg0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFB1Ymxpc2hlcixHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KIyMgey19DQpBdWZmw6RsbGlnIGlzdCBoaWVyIGRpZSBkaXNrcmVwYW56IHp3aXNjaGVuIEFuemFobCBkZXIgU3BpZWxlcmVsZWFzZXMgdW5kIEFuemFobCBkZXIgU3BpZWxldmVya8OkdWZlLiBJbSBnZWdlbnNhdHogenUgZGVyIEFuemFobCBkZXIgU3BpZWxlIChiZWkgZGVtIE5pbnRlbmRvIG51ciBhdWYgcGxhdHogNiBTaXR6KSBkb21pbmllcnQgTmludGVuZG8gaW0gYW56YWhsIGRlciBTYWxlcy4NCg0KDQpOdW4gc3RlbGx0IHNpY2ggd2llZGVyIGVpbm1hbCBkaWUgRnJhZ2Ugb2Igc2ljaCBkaWVzIGluIEJlc3RpbW10ZW4gdGVpbGVuIGRlciBXZWx0IHVudGVyc2NoZWlkZXQgdW5kIGhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIHdpZWRlcnVtIGRpZSBTb3J0ZWRCYXIvUGllY2hhcnQga29tYm8gdW5kIGRpZSBiZXJlaXRzIGdlbmFubnRlbiBGaWx0ZXINCg0KKioqDQoNCiMgUHVibGlzaGVyIFJhbmtpbmcgbmFjaCBSZWdpb24geyNQdWJsaXNoZXJSYW5raW5nYnlSZWdpb259DQoNCiMjIFB1Ymxpc2hlciBSYW5raW5nIG5hY2ggUmVnaW9uIHsudGFic2V0fQ0KIyMjIEJhbGtlbmRpYWdyYW1tZSB7LnRhYnNldH0NCiMjIyMgRXVyb3BhDQoNCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19FVTEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKEVVX1NhbGVzKSkgJT4lDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEVVX1NhbGVzKSINCiAgICApDQoNClB1Ymxpc2hlclNhbGVzIDwtIHZnc2FsZXMgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgZmlsdGVyKEdsb2JhbF9TYWxlcz4zMDApDQoNCg0KDQpncm91cGVkIDwtIGdyb3VwZWQgICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkVVIFNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUHVibGlzaGVyLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJFVSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIg0KICAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iRVUgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQojIyMjIE5vcmQgQW1lcmlrYQ0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX05BMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oTkFfU2FsZXMpKSAlPiUNCiAgZmlsdGVyKEFuemFobD4xMDApICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIk5BIFNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUHVibGlzaGVyLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJOQSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIg0KICAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iTkEgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQojIyMjIEphcGFuDQpgYGB7ciBwbG90KFB1Ymxpc2hlclJhbmtpbmdfSlAxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpLHN1bShKUF9TYWxlcykpICU+JQ0KICBmaWx0ZXIoQW56YWhsPjEwMCkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShKUF9TYWxlcykiDQogICAgKQ0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJFbnRlcnRhaW5tZW50IikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJJbnRlcmFjdGl2ZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiU3R1ZGlvcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZXMiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC0gYXNfZmFjdG9yKG9yZGVyZWQkUHVibGlzaGVyKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlB1Ymxpc2hlciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiSlAgU2FsZXMgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQdWJsaXNoZXIsR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IkpQIFNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJKUCBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIEtyZWlzZGlhZ3JhbW1lIHsudGFic2V0fQ0KDQojIyMjIEV1cm9wYQ0KDQpgYGB7ciBwbG90KFB1Ymxpc2hlclJhbmtpbmdfRVUpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKEVVX1NhbGVzKSkgJT4lDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEVVX1NhbGVzKSINCiAgICApDQoNClB1Ymxpc2hlclNhbGVzIDwtIHZnc2FsZXMgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgZmlsdGVyKEdsb2JhbF9TYWxlcz4zMDApDQoNCg0KDQpncm91cGVkIDwtIGdyb3VwZWQgICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+UHVibGlzaGVyLA0KICAgICAgICAgICBuYW1lPSJFVSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIg0KICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJFVSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIyBOb3JkLUFtZXJpa2ENCg0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX05BMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oTkFfU2FsZXMpKSAlPiUNCiAgZmlsdGVyKEFuemFobD4xMDApICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIk5BIFNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5QdWJsaXNoZXIsdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLA0KICAgICAgICAgICBuYW1lPSJOQSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIg0KICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJOQSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIyBKYXBhbg0KDQpgYGB7ciBwbG90KFB1Ymxpc2hlclJhbmtpbmdfSlAyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpLHN1bShKUF9TYWxlcykpICU+JQ0KICBmaWx0ZXIoQW56YWhsPjEwMCkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShKUF9TYWxlcykiDQogICAgKQ0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJFbnRlcnRhaW5tZW50IikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJJbnRlcmFjdGl2ZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiU3R1ZGlvcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZXMiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC0gYXNfZmFjdG9yKG9yZGVyZWQkUHVibGlzaGVyKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlB1Ymxpc2hlciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiSlAgU2FsZXMgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9flB1Ymxpc2hlciwNCiAgICAgICAgICAgbmFtZT0iSlAgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciINCiAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iSlAgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIHstfQ0KDQpad2lzY2hlbiBFVSB1bmQgVVMgbGFzc2VuIHNpY2ggaGllciBrYXVtIFVudGVyc2NoaWVkZSBmZXN0c3RlbGxlbiBpbiBKYXBhbiBoaW5nZWdlbiBpc3QgZWluZSB2ZXJzY2hpZWJ1bmcgenUgZXJrZW5uZW4uIEphcGFuaXNjaGUgUHVibGlzaGVyIGbDvGhyZW4gaGllcmJlaSBkaWUgTGlzdGUgYW4gdW5kIGRyw6RuZ2VuIGFuZGVyZSBncm/Dn2UgdW50ZXJuZWhtZW4gdm9uIGRlbiBUb3Agc3BvdHMuDQoNCioqKg0KDQojIEdlbnJldmVydGVpbHVuZyBkZXIgVmlkZW9zcGllbGUgbmFjaCBBbnphaGwgeyNHZW5yZUFtb3VudEdsb2JhbH0NCg0KTnVuIHNjaGF1ZW4gd2lyIHVucyBkaWUgR2VucmV2ZXJ0ZWlsdW5nIHZvbiBWaWRlb3NwaWVsZW4gYW4uIEhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIHdpZWRlcnVtIGRpZSBBbHRiZWthbm50ZSBzb3J0ZWQgQmFyL1BpZS1DaGFydCBrb21iby4NCg0KIyMgR2VucmUgQW1vdW50IHsudGFic2V0fQ0KDQojIyMgQmFsa2VuIERpYWdyYW1tDQoNCmBgYHtyIHBsb3QoR2VucmVBbW91bnRfR0xvYmFsMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKQ0KDQpncm91cGVkJEFuemFobDwtYXNfdmVjdG9yKGdyb3VwZWQkQW56YWhsKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkQW56YWhsKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRHZW5yZSA8LSBhc19mYWN0b3Iob3JkZXJlZCRHZW5yZSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoR2VucmUsQW56YWhsLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5BbnphaGwsDQogICAgICAgICAgIG5hbWU9IkFtb3VudCBieSBHZW5yZSINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkFtb3VudCBieSBHZW5yZSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KIyMjIEtyZWlzIERpYWdyYW1tDQoNCmBgYHtyIHBsb3QoR2VucmVBbW91bnRfR0xvYmFsMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKQ0KDQpncm91cGVkJEFuemFobDwtYXNfdmVjdG9yKGdyb3VwZWQkQW56YWhsKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkQW56YWhsKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRHZW5yZSA8LSBhc19mYWN0b3Iob3JkZXJlZCRHZW5yZSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5BbnphaGwsbGFiZWxzPX5HZW5yZSwNCiAgICAgICAgICAgbmFtZT0iQW1vdW50IGJ5IEdlbnJlIg0KICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJBbW91bnQgYnkgR2VucmUiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQojIyB7LX0NCg0KSGllcmJlaSBpc3QgenUgZXJrZW5uZW4gZGFzIEFjdGlvbiB1bmQgU3BvcnRzIGVpbiBHcm/Dn3RlaWwgKDM0JSkgZGVyIEdlbnJlcyBhdXNtYWNoZW4uIERpZSBGcmFnZSBpc3QgamVkb2NoIHdpZSBzaW5kIGRpZSBWZXJrw6R1ZmUgdmVydGVpbHQgdW5kIGJlZWluZmx1c3N0IGRpZSBhbnphaGwgZGVyIEdhbWVzIHBybyBHZW5yZSBpcmdlbmR3aWUgZGllIFZlcmthdWZzemFobGVuPw0KDQoNCg0KIyMgU2FsZXMgQW1vdW50IHsudGFic2V0fQ0KDQojIyMgQmFsa2VuIERpYWdyYW1tDQoNCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX0dsb2JhbDEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKEdlbnJlLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJTYWxlcyBieSBHZW5yZSINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQojIyMgS3JlaXMgRGlhZ3JhbW0NCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfR2xvYmFsMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5HZW5yZSwNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUiDQogICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICkNCmBgYA0KDQoNCiMjIHstfQ0KDQpIaWVyYmVpIGVya2VubmVuIHdpciBkYXMgZXMgZWluaWdlIFVudGVyc2NoaWVkZSBnaWJ0IEFjdGlvbiB1bmQgc3BvcnRzIG1hY2hlbiBqZWRvY2ggd2VpdGVyaGluIGVpbmVuIEdyb3N0ZWlsIGRlcyBNYXJrdHMgYXVzLg0KDQpOdW4gc2NoYXVlbiB3aXIgdW5zIGRpZSBVbnRlcnNjaGVpZGUgaW4gZGVuIFJlZ2lvbmVuIGFuLg0KDQojIFJlZ2lvbmFsZSBVbnRlcnNjaGllZGUgZGVyIEdlbnJlcyB7I0dlbnJlQW1vdW50QnlSZWdpb259DQoNCiMjIFNhbGVzYnlHZW5yZSB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbmRpYWdyYW1tZSB7LnRhYnNldH0NCg0KIyMjIyBFdXJvcGENCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfRVUxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oRVVfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShFVV9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoR2VucmUsR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IlNhbGVzIGJ5IEdlbnJlIChFVSkiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSAoRVUpIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIyBOb3JkLUFtZXJpa2ENCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX05BMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKEdlbnJlLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJTYWxlcyBieSBHZW5yZSAoTkEpIg0KICAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgKE5BKSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyMgSmFwYW4NCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfSlAxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oSlBfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShKUF9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoR2VucmUsR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IlNhbGVzIGJ5IEdlbnJlIChKUCkiICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSAoSlApIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQoNCiMjIyBLcmVpc2RpYWdyYW1tZSB7LnRhYnNldH0NCg0KIyMjIyBFdXJvcGENCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX0VVMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEVVX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oRVVfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5HZW5yZSwNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgKEVVKSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIChFVSkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgKQ0KYGBgDQoNCiMjIyMgTm9yZC1BbWVyaWthDQoNCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX05BMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+R2VucmUsDQogICAgICAgICAgIG5hbWU9IlNhbGVzIGJ5IEdlbnJlIChOQSkiLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIChOQSkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgKQ0KYGBgDQoNCiMjIyMgSmFwYW4NCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfSlAyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oSlBfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShKUF9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5HZW5yZSwNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgKEpQKSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIChKUCkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgKQ0KYGBgDQoNCiMjIHstfQ0KSGllcmJlaSBlcmtlbm5lbiB3aXIgd2llZGVyIGVpbm1hbCBkYXMgVVMgdW5kIEVVIHJlY2h0IMOkaG5saWNoIHNpbmQgd29oaW5nZWdlbiBKYXBhbiBlaW4gZ8OkbnpsaWNoIGFuZGVyZXMgR2VucmVzaGVtYSBlcmtlbm5lbiBsw6Rzc3QuIEluIEphcGFuIGRvbWluaWVydCBSb2xlLVBsYXlpbmcgd2VsY2hlcyBzaWNoIGluIEVVIHVuZCBVUyBudXIgYXVmIHBsYXR6IDcgYmVmaW5kZXQuDQoNCk51biBzY2hhdWVuIHdpciB1bnMgZGllIEdlbnJlZW50d2lja2x1bmcgw7xiZXIgZGllIEphaHJlIGFuLiBIaWVyenUgdmVyd2VuZGVuIHdpciBMaW5lUGxvdHMuDQoNCiMgR2VucmVlbnR3aWNrbHVuZyBpbSBsYXVmZSBkZXIgSmFocmUgbmFjaCBhbnphaGwgeyNHZW5yZUFtb3VudFBlclllYXJ9DQoNCiMjIEdlbnJlIEFtb3VudCBwZXIgWWVhciB7LnRhYnNldH0NCg0KIyMjIExpbmVzDQoNCmBgYHtyIHBsb3QoQW1vdW50T2ZHYW1lc0J5R2VucmVieVllYXIxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKEFuemFobCA9bigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLEFuemFobCkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoKSAlPiUgDQogIGFkZF9saW5lcyh4PX5ZZWFyLA0KICAgICAgICAgICB5PX5BbnphaGwsIGNvbG9yPX5HZW5yZSxjb2xvcnMgPSBteVBhbGV0dGUpDQoNCmBgYA0KDQojIyMgRmlsbGVkIExpbmVzDQoNCmBgYHtyIHBsb3QoQW1vdW50T2ZHYW1lc0J5R2VucmVieVllYXIyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKEFuemFobCA9bigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLEFuemFobCkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCg0KKQ0KDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+QW56YWhsLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBmaWxsID0gJ3RvemVyb3knLGNvbG9yID0gfkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpJT4lIA0KICBsYXlvdXQodGl0bGU9IkFtb3VudCBieSBHZW5yZSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KIyMjIFN0YWNrZWQgTGluZXMgey5hY3RpdmV9DQoNCmBgYHtyIHBsb3QoQW1vdW50T2ZHYW1lc0J5R2VucmVieVllYXIzKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKEFuemFobCA9bigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLEFuemFobCkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCg0KKQ0KDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+QW56YWhsLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsY29sb3IgPSB+R2VucmUsIGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQojIyMgR2VucmVzaGlmdCAlDQoNCmBgYHtyIHBsb3QoQW1vdW50T2ZHYW1lc0J5R2VucmVieVllYXI0KSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKEFuemFobCA9bigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLEFuemFobCkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlBlcmNlbnQgJSINCg0KKQ0KDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+QW56YWhsLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsZ3JvdXBub3JtID0gJ3BlcmNlbnQnLGNvbG9yID0gfkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpJT4lIA0KICBsYXlvdXQodGl0bGU9Ik1hcmtldGFtb3VudCBnZW5yZXNoaWZ0IGluICUgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQojIyB7LX0NCg0KSGllcmJlaSB6dSBlcmtlbm5lbiBpc3QgT2J3b2hsIGRpZSBBbnphaGwgZGVyIErDpGhybGljaGVuIFNwaWVsZXJlbGVhc2VzIMO8YmVyIGRpZSBKYWhyZSBoaW53ZWcgc3RldGlnIHfDpGNoc3QgYmxlaWJlbiBkaWUgTWVpc3RlbiBHZW5yZXMgw6RobmxpY2ggdmllbCB2ZXJ0cmV0ZW4uIEF1ZmbDpGxsaWcgc2luZCBoaWVyYmVpIFN0cmF0ZWd5LUdhbWVzIGRpZSBlcnN0IDE5OTEgZGFzIGVyc3RlIG1hbCBhdWZ0cmV0ZW0gU2VpdGRlbSBvYndvaGwgc2llIExlaWNodCBhbiBNYXJrZXRzaGFyZSB2ZXJsaWVyZW4gZ3JvYiBnbGVpY2ggYmxlaWJlbi4gQXXDn2VyZGVtIHNpbmQgQWN0aW9uIEdhbWVzIGRpZSBTcGllbGUgbWl0IGRlciB3b2hsIGdyw7bDn3RlbiB2b2xhdGlsaXTDpHQuIFNpbmQgZXMgMTk4MiBub2NoIGZhc3QgNTAlIGRlciBHYW1lcmVsZWFzZXMgZsOkbGx0IGRlcmVuIGF1ZmtvbW1lbiAxMDg0IHNjaG9uIGF1ZiBudXIgbm9jaCBrbmFwcCAxMCUgYWIgdW5kIDE5ODYgc3RlaWd0IGRlciBXZXJ0IHdpZWRlciBhdWYgZmFzdCAzMCUuIERpZXNlciBUcmVuZCBzZXR6dCBzaWNoIGZvcnQgYmlzIDE5OTYgYWIgd2VsY2hlbSBaZWl0cHVua3Qgc2ljaCBBY3Rpb24gR2FtZXMgdm9uIDMuNiUgw7xiZXIgZGllIEphaHJlIGJpcyAyMDE2IGJpcyAzNSUgZW50d2lja2Vsbi4NCg0KIyBHZW5yZWVudHdpY2tsdW5nIGltIGxhdWZlIGRlciBKYWhyZSBuYWNoIFZlcmthdWZzemFobGVuIHsjR2VucmVTYWxlc1BlclllYXJ9DQoNClNjaGF1ZW4gd2lyIHVucyBhbiB3aWUgc2ljaCBkaWUgdmVya8OkdWZlIGVudHdpY2tlbHQgaGFiZW4uDQoNCiMjIFNhbGVzIEFtb3VudCBwZXIgWWVhciB7LnRhYnNldH0NCg0KIyMjIExpbmVzDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZWJ5WWVhcjEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJHbG9iYWxfU2FsZXMiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KCkgJT4lIA0KICBhZGRfbGluZXMoeD1+WWVhciwNCiAgICAgICAgICAgeT1+Z3Jfc3VtLCBjb2xvcj1+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KIyMjIEZpbGxlZCBMaW5lcw0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZWJ5WWVhcjIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJHbG9iYWxfU2FsZXMiDQoNCikNCg0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdub25lJywgZmlsbCA9ICd0b3plcm95Jyxjb2xvciA9IH5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCiMjIyBTdGFja2VkIExpbmVzIHsuYWN0aXZlfQ0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZWJ5WWVhcjMpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJHbG9iYWxfU2FsZXMiDQoNCikNCg0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdub25lJywgc3RhY2tncm91cCA9ICdvbmUnLGNvbG9yID0gfkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIEdlbnJlc2hpZnQgJQ0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZWJ5WWVhcjQpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJQZXJjZW50ICUiDQoNCikNCg0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdub25lJywgc3RhY2tncm91cCA9ICdvbmUnLGdyb3Vwbm9ybSA9ICdwZXJjZW50Jyxjb2xvciA9IH5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSU+JSANCiAgbGF5b3V0KHRpdGxlPSJNYXJrZXRzaGFyZSBnZW5yZXNoaWZ0IGluICUgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQojIyB7LX0NCg0KV2llIHp1IGVyd2FydGVuIGzDpHNzdCBzaWNoIGhpZXIgZWluIEdyb8OfZXIgb3ZlcmxhcCB6dSBkZW4gQW56YWhsIGRlciBHYW1lcmVsZWFzZXMgZmVzdHN0ZWxsZW4uDQoNCiMgR2VucmVlbnR3aWNrbHVuZyBpbSBsYXVmZSBkZXIgSmFocmUgbmFjaCBWZXJrYXVmc3phaGxlbiBwcm8gU3BpZWwgeyNHZW5yZVNhbGVzUGVyR2FtZVBlclllYXJ9DQoNCk51biBzdGVsbHQgc2ljaCBkaWUgRnJhZ2UgaGFiIHNpY2ggZGllIFZlcmvDpHVmZSDDpGhubGljaCBkZXIgYW56YWhsIGRlciBHYW1lUmVsZWFzZXMgZW50d2lja2VsdD8NCg0KIyMgU2FsZXMgcGVyIEdhbWUgcGVyIFllYXIgey50YWJzZXR9DQoNCiMjIyBMaW5lcw0KYGBge3IgcGxvdChTYWxlc1BlckdhbWVQZXJHZW5yZWJ5WWVhcjEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIHBlciBHYW1lIg0KDQopDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSgpICU+JSANCiAgYWRkX2xpbmVzKHg9flllYXIsDQogICAgICAgICAgIHk9fmdyX3N1bSwgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBwZXIgR2FtZSBieSBHZW5yZSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KIyMjIEZpbGxlZCBMaW5lcw0KDQpgYGB7ciBwbG90KFNhbGVzUGVyR2FtZVBlckdlbnJlYnlZZWFyMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKS9uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMgcGVyIEdhbWUiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIGZpbGwgPSAndG96ZXJveScsY29sb3IgPSB+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIHBlciBHYW1lIGJ5IEdlbnJlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQojIyMgU3RhY2tlZCBMaW5lcyB7LmFjdGl2ZX0NCg0KYGBge3IgcGxvdChTYWxlc1BlckdhbWVQZXJHZW5yZWJ5WWVhcjMpLGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIEdlbnJlKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKS9uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsZ3Jfc3VtKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMgcGVyIEdhbWUiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxjb2xvciA9IH5HZW5yZSwgY29sb3JzID0gbXlQYWxldHRlKSU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBwZXIgR2FtZSBieSBHZW5yZSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyBHZW5yZXNoaWZ0ICUNCg0KYGBge3IgcGxvdChTYWxlc1BlckdhbWVQZXJHZW5yZWJ5WWVhcjQpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlBlcmNlbnQgJSINCg0KKQ0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxncm91cG5vcm0gPSAncGVyY2VudCcsY29sb3IgPSB+R2VucmUsIGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iTWFya2V0c2hhcmUgaW4gU2FsZXMgcGVyIEdhbWUgYnkgR2VucmUgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQojIyB7LX0NCkF1Y2ggaGllciBpc3Qgd2llIGVyd2FydGV0IGRpZSBFbnR3aWNrbHVuZyBQcm96ZW50dWFsIMOkaG5saWNoIHNpbmQuIEF1ZmbDpGxsaWcgaXN0IGplZG9jaCBkYXMgU2hvb3RlciB0cm90eiBpaHJlciBnZXJpbmdlbiBWZXJ0cmV0dW5nIGluIGRlciBQcm96ZW50dWFsZW4gVmVydGVpbHVuZyAxOTg0IHNvd2llIDIwMTQsMjAxNSB1bmQgMjAxNiBkaWUgTmFzZSBWb3JuZSBoYWJlbi4gUGxhdGZvcm0gR2FtZXMgaGFiZW4gMTk4NSwxOTg4IHVuZCAxOTkwIGRpZSBOYXNlIFZvcm5lLiBEaWUgSG9jaHplaXQgZGVyIFB1enpsZSBHYW1lcyBzaW5kIHVuYW5nZWZvY2h0ZW4gMTk4OCBtaXQgZGVtIFdlbHR3ZWl0YmVrYW5udGVuIHVuZCBhdWYgUGxhdHogNiBkZXIgbWVpc3R2ZXJrYXVmdGVuIHZpZGVvc3BpZWxlOiBUZXRyaXMuIEVpbiBnZW5hdWVyZXIgdmVyZ2xlaWNoIGRlciBBdXNzY2hsw6RnZSBtaXQgZGVuIGRlbWVudHNwcmVjaGVuZGVuIFZpZGVvc3BpZWxlbiB3w6RyZSBoaWVyIHfDvG5zY2hlbnN3ZXJ0IHfDvHJkZSBhYmVyIGRhcyBBdXNtYcOfIGRpZXNlciBBcmJlaXQgc3ByZW5nZW4uDQoNCg0KTnVuIHN0ZWxsdCBzaWNoIGRpZSBGcmFnZSB3aWUgZXMgbWl0IEdlbnJlcyBwcm8gcHVibGlzaGVyIGF1c3NpZWh0PyBHaWJ0IGVzIGhpZXIgUHVibGlzaGVyIGRpZSB2ZXJzY2hpZWRlbmUgR2VucmVzIGJldm9yenVnZW4gYnp3LiBkZXJlbiBCZXN0c2VsbGVyIHNpY2ggaW4gYmVzdGltbXRlbiBHZW5yZXMgVHVtbWVsbj8NCg0KSGllcnp1IHZlcndlbmRlbiB3aXIgZWluIHN0YWNrZWQgQmFyLVBsb3QuIERhenUgZmlsdGVybiB3aXIgZGllIHRvcCAxMCBQdWJsaXNoZXJuIGFrYSBQdWJsaXNoZXIgbWl0IG1pbiAxMTYgbWlvIGluIFNhbGVzLiBEaWVzIGVudGZlcm50IG5hdMO8cmxpY2ggZWluaWdlcyBhbiBJbmZvcm1hdGlvbiBhbGxlcmRpbmdzIGdlaHQgc29uc3QgZWluaWdlcyBhbiDDnGJlcnNpY2h0bGljaGtlaXQgdmVybG9yZW4uIFp1c8OkdHpsaWNoIHdlcmRlbiBlcm5ldXQgZGllIFdvcnRlICJFbnRlcnRhaW5tZW50IiwgIkludGVyYWN0aXZlIiwgIkdhbWUiLCAiR2FtZXMiIHVuZCAiU3R1ZGlvcyIgZW50ZmVybnQuDQoNCiMgR2VucmV2ZXJ0ZWlsdW5nIG5hY2ggUHVibGlzaGVyIHsjR2VucmVCeVB1Ymxpc2hlckdsb2JhbH0gIA0KDQojIyBHZW5yZSBieSBQdWJsaXNoZXIgey50YWJzZXR9DQoNCiMjIyBTYWxlcw0KDQpgYGB7ciBwbG90KFNhbGVzR2VucmVieVB1Ymxpc2hlciksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSANCg0KUHVibGlzaGVyU2FsZXMgPC0gZ3JvdXBlZCAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KZ3JvdXBlZCA8LSBncm91cGVkICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0KDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJHYW1lIikNCg0KICANCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIg0KDQopDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSh4PX5QdWJsaXNoZXIsDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgIHR5cGU9J2JhcicsDQogICAgICAgICAgIGNvbG9yPX5HZW5yZSwgY29sb3JzID0gbXlQYWxldHRlKSAgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIEJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCg0KYGBgDQoNCiMjIyBBbW91bnQNCg0KYGBge3IgcGxvdChBbW91bnRHZW5yZWJ5UHVibGlzaGVyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpLHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gZ3JvdXBlZCAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJHYW1lIikNCg0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbW91bnQiDQoNCikNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KHg9flB1Ymxpc2hlciwNCiAgICAgICAgICAgeT1+QW56YWhsLA0KICAgICAgICAgICAgdHlwZT0nYmFyJywNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIEJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCg0KDQpgYGANCg0KIyMgey19DQoNCkJlaSBkZW0gdmVyZ2xlaWNoIGRlciBXZXJ0ZSBpc3QgaGllciB6dSBiZW1lcmtlbiwgZGFzcyBkaWUgbWVpc3RlbiBQdWJsaXNoZXIgSGllcmJlaSBzaWNoIG1pdCBkZXIgQW56YWhsIGRlciBTcGllbGUgdW5kIGRlbiBTYWxlcyBndXQgYWJkZWNrZW4uIERpZSBhdWZmw6RsbGlnc3RlbiBkaXNrcmVwYW56ZW4gc2luZCBoaWVyYmVpIEVBIG1pdCBkZW0gU3BvcnRzIEdlbnJlIHVuZCBpaHJlbiBqw6RybGljaCByZWxlYXN0ZW4gU3BpZWxlbiBGaUZhL05CQTJrIGV0Yy4gc293aWUgTmludGVuZG8gbWl0IGRlciBQbGF0Zm9ybXJlaWhlIFN1cGVyIE1hcmlvLiBTY2hhdWVuIHdpciB1bnMgZGllc2UgQmVpZGVuIEZpcm1lbiBOb2NoIGVpbm1hbCBpbSBEZXRhaWwgYW4uDQoNCkhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIHdpZWRlciBkaWUgQmFyL1BpZSBjaGFydCBDb21ibyBkaWUgdW5zIEJlcmVpdHMgYXVzIHZvcmRlcmVuIFRlaWxlbiBkZXIgQXVzYXJiZWl0dW5nIGJla2FubnQgc2luZC4NCg0KIyBHZW5yZXZlcnRlaWx1bmcgZsO8ciBQdWJsaXNoZXIgRWxlY3Ryb25pYyBBcnRzeyNHZW5yZUJ5UHVibGlzaGVyRUF9IA0KDQojIyBHZW5yZSBmw7xyIEVsZWN0cm9uaWMgQXJ0cyB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbmRpYWdyYW1tZSB7LnRhYnNldH0NCg0KIyMjIyBTYWxlcyANCg0KYGBge3IgcGxvdChHZW5yZWJ5UHVibGlzaGVyRUExKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiRWxlY3Ryb25pYyBBcnRzIikNCg0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMiDQoNCikNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KCkgJT4lIGFkZF9iYXJzKHg9fkdlbnJlLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIGNvbG9yPX5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSAgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIGZvciBFbGVjdHJvbmljIEFydHMiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXksDQogICAgICAgICBiYXJtb2RlID0gJ3N0YWNrJw0KICAgICAgICAgKQ0KDQpgYGANCiMjIyMgQW1vdW50DQoNCmBgYHtyIHBsb3QoQW1vdW50R2VucmVieVB1Ymxpc2hlckVBMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKSAgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJFbGVjdHJvbmljIEFydHMiKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbW91bnQiDQoNCikNCg0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkFuemFobCwNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIGZvciBFbGVjdHJvbmljIEFydHMgIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgYmFybW9kZSA9ICdzdGFjaycNCiAgICAgICAgICkNCg0KYGBgDQojIyMgS3JlaXNkaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgU2FsZXMgDQoNCmBgYHtyIHBsb3QoR2VucmVieVB1Ymxpc2hlckVBMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgDQogIGZpbHRlcihQdWJsaXNoZXIgPT0gIkVsZWN0cm9uaWMgQXJ0cyIpDQoNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIg0KDQopDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5HZW5yZSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsc29ydCA9IEZBTFNFLA0KICAgICAgICAgICBuYW1lPSJTYWxlcyBieSBHZW5yZSBmb3IgRWxlY3Ryb25pYyBBcnRzIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgZm9yIEVsZWN0cm9uaWMgQXJ0cyIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQoNCmBgYA0KDQoNCiMjIyMgQW1vdW50DQoNCmBgYHtyIHBsb3QoQW1vdW50R2VucmVieVB1Ymxpc2hlckVBMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKSAgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJFbGVjdHJvbmljIEFydHMiKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbW91bnQiDQoNCikNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkFuemFobCxsYWJlbHM9fkdlbnJlLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50Jyxzb3J0ID0gRkFMU0UsDQogICAgICAgICAgIG5hbWU9IkFtb3VudCBieSBHZW5yZSBmb3IgRWxlY3Ryb25pYyBBcnRzIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIGZvciBFbGVjdHJvbmljIEFydHMiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQojIyB7LX0NClNjaGF1ZW4gd2lyIHVucyBFQSBoaWVyIGltIERldGFpbCBhbiBmw6RsbHQgYWxsZXJkaW5ncyBhdWYgZGFzIGRpZSBEaXNrcmVwYW56IHp3aXNjaGVuIFNhbGVzIHVuZCBBbnphaGwgZGVyIEdhbWVyZWxlYXNlcyBmw7xyIEVBIGJlaSBTcG9ydHMgZ2FyIG5pY2h0IHNvIGdyb8OfIGlzdCAoNDEuNSUgdnMgNDMuMiUpLiBEaWUgZ3LDtsOfZXJlbiBkaXNrcmVwYW56ZW4gc2luZCBoaWVyIFNob290ZXIgd2VsY2hlcyBudXIgMTAlIGRlciBHYW1lcmVsZWFzZXMgc2luZCBhYmVyIGd1dCAxNSUgZGVyIFNhbGVzIHVuZCBBY3Rpb24gbWl0IDEzLjUlIGRlciBHYW1lcmVsZWFzZXMgdW5kIDEwLjQlIGRlciBTYWxlcy4NCg0KIyBHZW5yZXZlcnRlaWx1bmcgZsO8ciBOaW50ZW5kbyB7I0dlbnJlQnlQdWJsaXNoZXJOaW50ZW5kb30gDQoNClNjaGF1ZW4gd2lyIHVucyBudW4gTmludGVuZG8gYW4uDQoNCiMjIEdlbnJlIGbDvHIgTmludGVuZG8gey50YWJzZXR9DQoNCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgU2FsZXMNCg0KYGBge3IgcGxvdChHZW5yZWJ5UHVibGlzaGVyTmludGVuZG8xKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiTmludGVuZG8iKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgZm9yIE5pbnRlbmRvIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgYmFybW9kZSA9ICdzdGFjaycNCiAgICAgICAgICkNCg0KDQpgYGANCg0KDQojIyMjIEFtb3VudA0KYGBge3IgcGxvdChBbW91bnRHZW5yZWJ5UHVibGlzaGVyTmludGVuZG8xKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpICAlPiUgDQogIGZpbHRlcihQdWJsaXNoZXIgPT0gIk5pbnRlbmRvIikNCg0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW1vdW50Ig0KDQopDQoNCg0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkFuemFobCwNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIGZvciBOaW50ZW5kbyIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCmBgYA0KDQojIyMgS3JlaXNkaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgU2FsZXMNCg0KYGBge3IgcGxvdChHZW5yZWJ5UHVibGlzaGVyTmludGVuZG8yKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiTmludGVuZG8iKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+R2VucmUsdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLHNvcnQgPSBGQUxTRSwNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgZm9yIE5pbnRlbmRvIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgZm9yIE5pbnRlbmRvIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCg0KYGBgDQoNCiMjIyMgQW1vdW50DQoNCmBgYHtyIHBsb3QoQW1vdW50R2VucmVieVB1Ymxpc2hlck5pbnRlbmRvMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKSAgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJOaW50ZW5kbyIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFtb3VudCINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+QW56YWhsLGxhYmVscz1+R2VucmUsdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLHNvcnQgPSBGQUxTRSwNCiAgICAgICAgICAgbmFtZT0iQW1vdW50IGJ5IEdlbnJlIGZvciBOaW50ZW5kbyIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkFtb3VudCBieSBHZW5yZSBmb3IgTmludGVuZG8iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCiMjIHstfQ0KDQpCZWkgTmludGVuZG8genUgZXJrZW5uZW4gaXN0IGhpZXIsIGRhc3MgUGxhdGZvcm0gc3BpZWxlIGVpbiBLYXNzZW5jaGxhZ2VyIHNpbmQuIE5laG1lbiBkaWVzZSBudXIgMTYlIGRlciBzcGllbGVyZWxlYXNlcyBlaW4gc28gYnJpbmdlbiBzaWUgZGVubm9jaCAyNCUgZGVyIFNhbGVzIGVpbi4gR2xlaWNoZXMgR2lsdCBmw7xyIFNwb3J0IGdhbWVzLiA4JSBnZWdlbsO8YmVyIDEyJS4gQWN0aW9uICgxMSUgdnMgNyUpLCBNaXNjICgxNCUgdnMgMTAlKSB1bmQgUHV6emxlIEdhbWVzICgxMC41JSB2cyA3JSkgc2luZCBqZWRvY2ggbmljaHQgc28gZXJmb2xncmVpY2guDQoNCg0KIyBBdXNibGljayBpbiBkaWUgWnVrdW5mdCB7I0F1c2JsaWNrSW5EaWVadWt1bmZ0fQ0KDQpFaW4gVmVyZ2xlaWNoIGRlciBBdXNzY2hsw6RnZSBtaXQgZGVuIGRlbWVudHNwcmVjaGVuZGVuIFZpZGVvc3BpZWxlbi4NCg0KRWluZSBnZW5hdWUgQW5hbHlzZSBkZXIgR2FtZXNhbGVzIHBybyBqYWhyIChha2EgdGV0cmlzdCAxOTUwIDMwIG1hbCB0ZXN0cmlzIDIwMTUgMzAwMDAwIG1hbCkgZ2ViZW4gZGllIGRhdGVuIG5pY2h0IGhlci4NCg0KZWluZSBhbnlsc2UgZGVyIENvcm9uYXBhbmRlbWllIHZlcsOkbmRlcnVuZ2VuIChnZWJlbiBkaWUgZGF0ZW4gbmljaHQgaGVyKQ0KDQpQbGF0Zm9ybWFuYWx5c2U6IFZlcmthdWZ0ZW4gU3BpZWxlIHBybyBTcGllbCBwcm8gcGxhdGZvcm0NCg0KIyBBdWZnZXRyZXRlbmUgUHJvYmxlbWUgeyNBdWZnZXRyZXRlbmVQcm9ibGVtZX0NCg0KQ29sb3JicmV3ZXIgd2lyZCBuaWNodCBpbiBqZWRlciBHcmFmaWsgYWt6ZXB0aWVydA0KDQpTYWxlcyBwcm8gR2FtZSBhbmFseXNlIHJlY2huZXQgbmljaHQgc3BpZWxlIHBybyBwbGF0Zm9ybSB6dXNhbW1lbg0KDQpNb2JpbGVnYW1lcyBmZWhsZW4gaW0gZGF0ZW5zYXR6IHVtZmFzdCBudXIgMTZrIGdhbWUgdm9uIHdlbHR3ZWl0IG1laHIgYWxzIDMuMyBtaW8gaHR0cHM6Ly93d3cuc3RhdGlzdGEuY29tL3N0YXRpc3RpY3MvMjkzMzA0L251bWJlci12aWRlby1nYW1lcnMvIzp+OnRleHQ9SW4lMjB0b3RhbCUyQyUyMHRoZXJlJTIwd2VyZSUyMGFuLGJpbGxpb24lMjBnYW1lcnMlMjBhY3Jvc3MlMjB0aGUlMjBnbG9iZS4NCg0Kb2Z0IGRvcHBlbHRlciBjb2RlIGR1cmNoIHZlcndlbmR1bmcgaW4gbWVocmVyZW4gRGlhZ3JhbW1lbiBtaXQgbnVyIGxlaWNodGVuIMOkbmRlcnVuZ2VuDQoNClBsYXRmb3JtYW5hbHlzZSBuYWNoIHJlZ2lvbiBWZXJnbGVpY2ggaW4gYW56YWhsIGRlciBTcGllbGUgbmljaHQgbcO2Z2xpY2ggZGEgaGVya3VuZnRzbGFuZCBkZXMgc3BpZWxzIG5pY2h0IGtsYXINCg0KUmVnaW9uYWxlciB2ZXJnbGVpY2ggYXVmZ3J1bmQgdm9uIHVudGVyc2NoaWVkbGljaGVuIGVud29obmVyIHphaGxlbiBudXIgcHJvemVudHVhbCBuaWNodCBhYnNvbHV0IG3DtmdsaWNo
Created by Florian Reichle
flre0005@hs-kl.de